下图是Struts的工作流程,前边我们提到,所有的请求都提交给ActionServlet来处理。
ActionServlet是一个FrontController,它是一个标准的Servlet,它将request转发给RequestPRocessor来处理,
ActionMapping是ActionConfig的子类,实质上是对struts-config.xml的一个映射,从中可以取得所有的配置信息
RequestProcessor根据提交过来的url,如*.do,从ActionMapping中得到相应的ActionForn和Action。然后将request的参数对应到ActionForm中,进行form验证。假如验证通过则调用Action的execute()方法来执行Action,最终返回ActionFoward。
ActionFoward是对mapping中一个foward的包装,对应于一个url
ActionForm使用了ViewHelper模式,是对Html中form的一个封装。其中包含有validate方法,用于验证form数据的有效性。ActionForm是一个符合javaBean规范的类,所有的属性都应满足get和set对应。对于一些复杂的系统,还可以采用DynaActionForm来构造动态的Form,即通过预制参数来生成Form。这样可以更灵活的扩展程序。
ActionErrors是对错误信息的包装,一旦在执行action或者form.validate中出现异常,即可产生一个ActionError并最终加入到ActionErrors。在Form验证的过程中,假如有Error发生,则会将页面重新导向至输入页,并提示错误。
Action是用于执行业务逻辑的RequsestHandler。每个Action都只建立一个instance。Action不是线程安全的,所以不应该在Action中访问特定资源。一般来说,应改使用BusinessDelegate模式来对Businesstier进行访问以解除耦合。
Struts提供了多种Action供选择使用。普通的Action只能通过调用execute执行一项任务,而DispatchAction可以根据配置参数执行,而不是仅进入execute()函数,这样可以执行多种任务。如insert,update等。LookupDispatchAction可以根据提交表单按钮的名称来执行函数。
我们可以先回到刚才的例子,理解一下Struts的流程。
下面我们看Struts自带的example实例:
说明:实例二是Struts自带的example程序,实现了登录,注册,修改功能。
代码中大量应用了strutstaglib,并且采用validator插件进行form的验证。
但是代码树立了一个不好的榜样,即把大量的业务逻辑写在了action中。
部分代码如下:
登录:logon.jsp
<%@pagecon_tentType="text/html;charset=UTF-8"language="java"%>
//声明Taglib
<%@tagliburi="/WEB-INF/struts-bean.tld"prefix="bean"%>
<%@tagliburi="/WEB-INF/struts-html.tld"prefix="html"%>
<html:htmllocale="true">
<head>
//bean是用来从applicationResource中读取i18n信息
<title><bean:messagekey="logon.title"/></title>
<html:base/>
</head>
<bodybgcolor="white">
//错误信息部分
<html:errors/>
//登录form,action为logion.do
<html:formaction="/logon"focus="username"
on_submit="returnvalidateLogonForm(this);">
<tableborder="0"width="100%">
<tr>
<thalign="right">
<bean:messagekey="prompt.username"/>:
</th>
<tdalign="left">
<html:textproperty="username"size="16"maxlength="18"/>
</td>
</tr>
<tr>
<thalign="right">
<bean:messagekey="prompt.passWord"bundle="alternate"/>:
</th>
<tdalign="left">
<html:passwordproperty="password"size="16"maxlength="18"redisplay="false"/>
</td>
</tr>
<tr>
<tdalign="right">
<html:submitvalue="Submit"/>
</td>
<tdalign="left">
<html:reset/>
</td>
</tr>
</table>
</html:form>
//Validator插件,用于form验证
<html:javascriptformName="logonForm"dynamicJavascript="true"staticJavascript="false"/>
<scriptlanguage="Javascript1.1"src="staticJavascript.jsp"></script>
</body>
</html:html>
struts-config.xml配置
<form-beans>
<!--Logonformbean-->
<form-beanname="logonForm"type="org.apache.struts.validator.DynaValidatorForm">
<form-propertyname="username"type="java.lang.String"/>
<form-propertyname="password"type="java.lang.String"/>
</form-bean>
<!--Subscriptionformbean-->
<form-beanname="subscriptionForm"type="org.apache.struts.webapp.example.SubscriptionForm"/>
</form-beans>
<action-mappings>
<!--Editmailsubscription-->
<actionpath="/editSubscription"
type="org.apache.struts.webapp.example.EditSubscriptionAction"
attribute="subscriptionForm"
scope="request"
validate="false">
<forwardname="failure"path="/mainMenu.jsp"/>
<forwardname="sUCcess"path="/subscription.jsp"/>
</action>
...
subscriptionForm是一个标准的ActionForm,其中reset方法用于清除form的值,validate方法用于验证
publicfinalclassSubscriptionFormextendsActionForm{
//Themaintenanceactionweareperforming(CreateorEdit).
privateStringaction="Create";
//Shouldweauto-connectatstartuptime?
privatebooleanautoConnect=false;
//Thehostname.
privateStringhost=null;
privateStringpassword=null;
privateStringtype=null;
privateStringusername=null;
publicStringgetAction(){return(this.action);}
publicvoidsetAction(Stringaction){this.action=action;}
publicbooleangetAutoConnect(){return(this.autoConnect);}
publicvoidsetAutoConnect(booleanautoConnect){this.autoConnect=autoConnect;}
publicStringgetHost(){return(this.host);}
publicvoidsetHost(Stringhost){this.host=host;}
publicStringgetPassword(){return(this.password);}
publicvoidsetPassword(Stringpassword){this.password=password;}
publicStringgetType(){return(this.type);}
publicvoidsetType(Stringtype){this.type=type;}
publicStringgetUsername(){return(this.username);}
publicvoidsetUsername(Stringusername){this.username=username;}
/**
*Resetallpropertiestotheirdefaultvalues.
*
*@parammappingThemappingusedtoselectthisinstance
*@paramrequestTheservletrequestweareprocessing
*/
publicvoidreset(ActionMappingmapping,HttpServletRequestrequest){
this.action="Create";
this.autoConnect=false;
this.host=null;
this.password=null;
this.type=null;
this.username=null;
}
/**
*ValidatethepropertiesthathavebeensetfromthisHTTPrequest,
*andreturnan<code>ActionErrors</code>objectthatencapsulatesany
*validationerrorsthathavebeenfound.Ifnoerrorsarefound,return
*<code>null</code>oran<code>ActionErrors</code>objectwithno
*recordederrormessages.
*
*@parammappingThemappingusedtoselectthisinstance
*@paramrequestTheservletrequestweareprocessing
*/
publicActionErrorsvalidate(ActionMappingmapping,
HttpServletRequestrequest){
ActionErrorserrors=newActionErrors();
if((host==null)(host.length()<1))
errors.add("host",
newActionError("error.host.required"));
if((username==null)(username.length()<1))
errors.add("username",
new