Posted on 2007-06-01 11:16
筱筱 阅读(284)
评论(0) 编辑 收藏 所属分类:
Struts学习日记
1.分析helloapp应用的需求
·接受用户输入的姓名<userName>,然后返回字符串"Hello<userName>!"。
·如果用户没有输入姓名就提交表单,将返回出错信息,提示用户首先输入姓名。
·如果用户输入姓名为"Monster",将返回出错信息,拒绝向"Monster"打招呼。
2. 运用Struts框架
·模型包括一个JavaBean组件PersonBean,它有一个userName属性,代表用户输入的名字。它提供了get/set方法,分别用于读取和设置userName属性,它还提供一个save()方法,负责把userName属性保存到持久化存储系统中,如数据库或文件系统。对于更为复杂的Web应用,JavaBean组件可以作为EJB或Web服务的前端组件。
·视图包括一个JSP文件hello.jsp,它提供用户界面,接受用户输入的姓名。视图还包括一个ActionForm Bean,它用来存放表单数据,并进行表单验证,如果用户没有输入姓名就提交表单,将返回出错信息。
·控制器包括一个Action类HelloAction,它完成三项任务:1.进行业务逻辑验证,如果用户输入的姓名为"Monster", 将返回错误消息;2.调用模型组件PersonBean的save()方法,保存用户输入的名字;3.决定将合适的视图组件返回给用户。
·除了创建模型、视图和控制器组件,还需要创建Struts的配置文件struts-config.xml,它可以把这些组件组装起来,使它们协调工作。此外,还需要创建整个Web应用的配置文件web.xml。
3.创建视图组件
本例中,视图包括两个组件:
·一个JSP文件:hello.jsp
·一个ActionForm Bean: HelloForm Bean (HelloForm.java)。
其中,jsp中有代码<html:bean action="/HelloWorld" focus="userName">
当用户提交了HTML表单后,Struts框架将自动把表单数据组装到ActionForm Bean中。ActionForm Bean中的属性和HTML表单中的字段一一对应。ActionForm Bean还提供了数据验证方法,以及把属性重新设置为默认值的方法。Struts框架中定义的ActionForm类是抽象的,必须在应用中创建它的子类,来存放具体的HTML表单数据。
HelloForm.java中有两个特殊的方法:
·validate():用于表单验证。
·reset():把属性重新设置为默认值。
本例中的资源文件是application.properties,用来存放数据信息。
4.创建控制器组件:HelloAction.java
控制器组件包括ActionServlet类和Action类。ActionServlet类是Struts框架自带的,它是整个Struts框架的控制枢纽,通常不需要扩展。Struts框架提供了可供扩展的Action类,它用来处理特定的HTTP请求。
所有的Action类都是org.apache.struts.action.Action的子类,Action子类应该覆盖父类的execute()方法。
HelloAction.java的代码如下:
package hello;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;
import com.yourcompany.struts.PersonBean;
import com.yourcompany.struts.form.HelloForm;
/**
* @struts.action path="/hello" name="helloForm" input="/form/hello.jsp" scope="request" validate="true"
*/
public final class HelloAction extends Action {
/**
* Method execute
* @param mapping:ActionMapping包含了这个Action的配置信息和Struts-config.xml文件中的<action>元素对应。
* @param form:ActionForm包含了用户的表单数据,当Struts框架调用execute()方法时,ActionForm中的数据
*已经通过了表单验证。
* @param request:HttpServletRequest当前的HTTP请求对象
* @param response:HttpServletResponse当前的HTTP响应对象
* @return ActionForward
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
/* These "massage come from the ApplicationResources.properties file"
* getResources(HttpServletRequest request)方法返回当前默认的MessageResource对象,它封装了Resource
*Bundle 中的文本内容。
* 接下来Action类就可以通过MessageResource对象来访问文本内容。例如:如果要读取消息key
*为"hello.jsp.title"对应的文本内容,可以调用MessageResources类的getMessage(String key)方法:
*String title=messages.getMessage("hello.jsp.title");
* MessageResources messages=getResources(request);
*/
/*
* Validate the request parameters specified by the user
* Note: Basic field validation done in HelloForm.java
* Business logic validation done in HelloAction.java
* 如果用户输入的姓名为"Monster",将创建包含错误信息的AcrionMessage对象,ActionMessage对象被保存
*到ActionMessages对象中。接下来调用在Action基类中定义的saveErrors()方法,它负责把ActionMessages
*对象保存到request范围内。最后返回ActionForward对象,Struts框架会根据ActionForward对象包含的转发
*信息把请求转发到恰当的视图组件,视图组件通过<html:errors>标签把request范围内的ActionMessages对象
*中包含的错误消息显示出来,提示用户修改错误。
* */
ActionMessages errors=new ActionMessages();
String userName=(String)((HelloForm) form).getUserName();
String badUserName="Monster";
if(userName.equalsIgnoreCase(badUserName))
{
//equalsIgnoreCase方法同vequals,只不过equalsIgnoreCase 是忽略大小写。
errors.add("username",new ActionMessage("hello.dont.talk.to.monster",badUserName));
saveErrors(request,errors);
return (new ActionForward(mapping.getInput()));
}
/*
* HelloAction类创建了一个模型组件PersonBean对象,并调用它的saveToPersistentStore()方法来保存userName
*属性。
* from the View,we now update the model
*
* */
PersonBean pb=new PersonBean();
pb.setUserName(userName);
pb.saveToPersistentStore();
/*
* 把PersonBean对象保存在request范围内内
* 从request范围内删除ActionForm Bean。由于后续的请求转发目标组件不再需要HelloForm Bean,所以
*可将它删除。当HelloAction类调用HttpServletRequest的setAttribute()方法,向hello.jsp传递PersonBean对象时,
*需要提供一个名为“persinbean”的属性key:request..setAttribute("personbean",pb);
* hello.jsp通过这个名为"personbean"的属性来读取PersonBean对象:
* <login:present name="personbean" scope="request">
* <h2>Hello <bean:write name="personbean" property="userName"/>!</h2>
* </logic:persent>
* 对于Struts应用,提倡将这些属性key常量定义在一个Java文件Constant.java中,例如本例。
* */
request.setAttribute(com.yourcompany.struts.Constants.PERSON_KEY,pb);
request.removeAttribute(mapping.getAttribute());
return (mapping.findForward("SayHello"));
}
}
5.创建模型组件
本例的模型组件是PersonBean.java,PersonBean是一个非常简单的JavaBean,它包括一个userName属性,以及相关的get/set方法。此外,它还有一个业务方法saveToPersistentStore()。
6. 创建存放常量的Java文件:Constant.java
7.创建配置文件web.xml和struts-config.xml
本例的运行流程为:
1.Servlet容器在web.xml文件中寻找<url-pattern>属性为"*.do"的<servlet-mapping>元素:
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2.Servlet容器依据以上<servlet-mapping>元素的<servlet-name>属性"action",在web.xml文件中寻找匹配的<servlet>元素:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
3.Servlet容器把请求转发给以上<servlet>元素指定的ActionServlet,ActionServlet依据用户请求路径"/HelloWorld",在Struts配置文件中检索path属性为"/HelloWorld"的Action元素:
<action
path="/HelloWorld"
type="hello.HelloAction"
name="HelloForm"
attribute="inputForm"
scope="request"
validate="true"
input="/hello.jsp"
>
<forward name="SayHello" path="/hello.jsp" />
</action>
4.ActionServlet根据<action>元素的name属性,创建一个HelloForm对象,把客户提交的表单数据传给HelloForm对象,再把HelloForm对象保存在<action>元素的scope属性指定的request范围内。
5.由于<action>元素的validate属性为true,ActionServlet调用HelloForm对象的validate()方法执行表单验证。
·当文本框中不输入姓名的时候,vallidate()方法返回一个ActionErrors对象。
ActionServlet把HelloForm的validate()方法返回的ActionErrors对象保存在request范围内,然后根据<action>元素的input属性,把客户请求转发给hello.jsp。
·当文本框中输入姓名"Monster"的时候,vallidate()方法返回ActionErrors对象中不包含任何ActionMessage对象,表示表单验证成功。
ActionServlet查找HelloAction实例是否存在,如果不存在就创建一个实例,然后调用HelloAction的execute()方法。
HelloAction的execute()方法先进行逻辑验证,由于没有通过逻辑验证,就创建一个ActionMessage对象,这个ActionMessage对象封装了错误消息,execute()方法把ActionMessage对象保存在ActionMessages对象中,再把ActionMessages对象存放在request范围内。最后返回一个ActionForward对象,该对象包含的请求转发路径为<action>元素的input属性指定的hello.jsp。
·当文本框中输入其他姓名的时候,vallidate()方法返回ActionErrors对象中不包含任何ActionMessage对象,表示表单验证成功。
HelloAction的execute()方法进行逻辑验证,这次通过了验证,然后执行相关的业务逻辑,最后调用ActionMapping.findForward()方法,参数为“SayHello”:return (mapping.findForward("SayHello"));
ActionMapping.findForward()方法从<action>元素中寻找name属性为“SayHello”的<forward>子元素,然后返回与之对应的ActionForward对象,它代表的请求转发路径为“/hello.jsp”。
HelloAction的execute()方法把ActionForward对象返回给ActionServlet,ActionServlet再把客户请求转发给hello.jsp。
hello.jsp的<bean:message>标签从Resource Bundle中读取文本,把它们输出到网页上,最后生成动态网页。