除了基本的Action 之外, Struts 还提供了几个其他类型的Action ,这些Action 大大丰富了Struts 的功能。下面介绍如下儿个常用的Action 。
• DispatchAction: 能同时完成多个Action 功能的Action 。 • ForwardActon: 该类用来整合Struts 和其他业务逻辑组件,通常只对请求作有效性检查。 • IncludeAction: 用于引入其他的资源和页面。 • LookupDispatchAction: DispatchAction 的子类,根据按钮的key ,控制转发给action的方法。 • MappingDispatchAction: DispatchAction 的子类,一个action 可映射出多个Action地址。 • SwitchAction: 用于从一个模块转换至另一个模块,如果应用分成多个模块时,就可以使用SwitchAction 完成模块之间的切换。 下面对常用的Action 进行介绍。 1 DispatchAction 及其子类 DispatchAction 是仅次于Action,使用最频繁的Action。用于同一个表单中有两个提交按钮时,但提交需要的逻辑处理完全不同的情况。如图3.28 所示为登录页面。 图3.28 两个提交按钮的表单页 该页面包含了两个提交按钮,但提交按钮需要执行的逻辑却不一样。最容易想到的 解决方法是,为每个按钮增加JavaScipt脚本,提交两个按钮时候分别提交给不同的Action处理。这是最容易想到,也最麻烦的方式。 Struts 提供了DispatchAction,可支持多个逻辑处理。对于上面的示例,表单需要两个逻辑处理:增加和修改。下面是示例所使用的Action 类的源代码: public class LoginAction extends DispatchAction { //***第一个处理逻辑 public ActionForward add(ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception System.out.pritln( "增加") ; request. setAt tribute ("method" , "增加") ; return mapping.findForward("success"); //*****第二个处理逻辑 public ActionForward modify(ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception System.out.println(" 修改n) ; request. setAttribute ("method回"修改") ; return mapping.findForward("success"}; 上面的Action 非常简单,其两个逻辑处理也非常简单。该Action 并没有重写execute方法,而是书写了两个自定义的方法:add 和modi句。这两个方法除了方法名与execute方法不同之外,其他的参数列表及异常的处理完全相同。这两个方法正是execute 方法的替代,用于完成业务逻辑的处理。 问题的关键是: Struts 如何区别不同表单提交与方法之间的对应关系?因为当使用DispatchAction 要求表单提交时,会额外多传递一个参数,该参数用于区分到底调用Action 中的哪个方法。 这个参数名在struts-config.xml 文件中指定。注意下面action 的配置代码: <action path="/login" type="lee.LoginAction name="1og inForm" scope="request" validate="true" input="/login.jsp" parameter="method"> <forward name="success" path="/welcome.jsp"/> </action> 在该action 的配置中,增加了parameter属性,该属性用于指定参数名,即Struts 将根据该参数的值调用对应的方法。为了让请求增加method 的参数,对上面的JSP 页面代码进行简单修改,可在JSP 页面中增加一个隐藏域,使该隐藏域的名字为method。下面是JSP 页面的表单代码: <html:form action="login.do"> <table border="O" width="100革"> <tr> <th align="left"><bean:message key="username"/></th> <td align="left"><html:text property="username" size="15"/></td> </tr> <tr> <th align="left"><bean:message key="pass"/></th> <td align="left"><html:text property="pass" size="15"/></td> </tr> <tr><td>
<input type="hidden" name="method" value="add"/> <input type="submit" value='<bean:message key="button.add"/> onClick="method.value='add'''/> <input type="submit" value='<bean:message key="button.modify"/>'onClick="method.value='modify'''/> <input type="reset" value='<bean:message key="button.reset"/>'/> </td> </tr> </table> </html:form> 从上面的代码中可以看到,页面中增加了method 的隐藏域,该隐藏域的默认值为add,当单击页面中的【修改】按钮时,该隐藏域的值将变成modify,单击【添加】按钮时,该隐藏域的值变成add。这个隐藏域就是额外传递的参数值,用于告诉Dispatch调用哪个方法来处理请求。 如果method 参数的值为add,将调用add 方法;如果method 参数的值为modify,则调用modify 方法。因此在单击不同按钮时,DispatchAction将可自动调用对应的方法来完成处理。 2 使用MappingDispatchAction MappingDispatchAction可将同一个Action 的不同方法映射成多个Action URI ,这种Action 的写法与DispatchAction 非常相似,同样不需要重写execute 方法,而是将书写多个自定义的方法。这些方法除了方法名与execute 方法不同外,其他的参数列表及异常处理完全一样。 下面是本示例所使用的Action 的源代码: public class LoginAct工on extends MappingDispatchAction II 第一个处理逻辑 public ActionForward add(ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse respo口se) throws Exception System.out.println("增加") ; request.setAttribute( 咱ethod" , "增加") ; return mapping.f工口dForward("success"); } II 第二个处理逻辑 public ActionForward modify(ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response)throws Exception System.out.println("修改") ; request.setAttribute( 叮nethod" "修改") ; return mapping.findForward("success"); 该Action 与前面的DispatchAction 没有太大的区别,仅仅改变它的父类: MappingDispatchAction,但变化在于该Action 的配置,看下面关于该Action 的配置代码: <1- 配置第一个Action. 实现类是lee.LoginAction , parameter 为add--> <action path="/add" type="lee.LoginAction" name="loginForm" scope="request" val 工date="true" input="logi口.jsp" parameter="add"> <forward name="success" path="/welcome.jsp"l> </action> <! 配置第二个Action. 实现类是lee.LoginAction , parameter 为modify--> <action path="/modify" type="lee.LoginAction" 口ame="log工口Formll scope工"request" validate="true" input="login.jsp阴parameter="modify"> <forward 口ame="success" path="/welcome.jsp"l> </action> 在这种情况下,两个action 使用的是同一个Action 处理类,只是调用的方法不同,同样也可达到上面的效果。当然也需要为页面中的两个按钮增加相应的JavaScript脚本,当单击不同按钮时,表单可提交到不同的action,下面是JSP 页面三个按钮的源代码: <td> <input type="submit" value='<bean:message key="button.add"/>' onClick="document.loginForm.action='add.do'''/> <input type="submit" value='<bea口:message key="button.modify"I>' onClick="document.loginForm.action='modify.do'''I> <input type="reset" value='<bean:message key="button.reset"I>'I> <ltd> 其中,前面两个提交按钮都增加了onClick 方法,即单击该按钮时,会改变表单的提交地址。
注意:使用MappingDispatchAction 并没有带来太大的优势,系统完全可以书写两个Action ,分别定义两个不同的action 映射,而其他部分没有区别。
3使用LookupDispatchAction LookupDispatchAction也是DispatchAction 的一种,但它的处理更加简单。该Action也可包含多个处理方法,它可让处理方法与按钮直接关联,无须使用任何的JavaScript脚本。 使用LookupDispatchAction时,提交按钮必须使用Struts 的html 标签,下面是该示例按钮部分的源代码: <td> <html:submit property="method"> <bean:message key="button.add"l> </html:submit> <html:submit property="method"> <bean:message key="button.modify"l> </html:submit> <input type="reset" value='<bean:message key="button.reset"I>'I> </td> 代码中两个提交按钮分别增加了property 属性,该属性的值为method。而在action的配置中,也使用parameter作为参数,看下面的action 配置代码: <action path="/login" type="lee.LoginAction" name="loginForm" scope="request" validate="true" input="/login.jsp" parameter="method"> <forward name="success" path="/welcome.jsp"l> </action> 这段配置代码表明:该action 也根据method 参数来区分请求分别调用哪个方法,此时无须使用method 的隐藏域,而是将按钮的property 设为method。通过这种方式可以避免书写JavaScript脚本。 因此可通过重写getKeyMethodMap方法完成按钮与Action 中方法的关联,下面是该Action 的源代码: public class LoginAction extends LookupDispatchAction { II 用于关联按钮和方法 protected Map getKeyMethodMap() Map map = new HashMap(); II如果按钮标题的key 为button.add. 则提交该按钮时对应add 方法 map .put ("button. add" , "add"); II如果按钮标题的key 为button.modify. 则提交该按钮时对应modify 方法 map.put ("button.modify" , "mod工fy") ; return map; } II 第一个处理逻辑 public ActionForward add(ActionMapping mapping, ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception System.out.println(" 增加II) i request.setAttribute("method" , "增加") ; return mapp工ng.f工ndForward(" success") ; } 第二个处理逻辑 public ActionForward modify(ActionMapping mapping , ActionForm form , HttpServletRequest request , HttpServletResponse response) throws Exception System.out.println("修改II) ; request.setAttribute( 咱ethod II II 修改II) ; return mapping.findForward("success"); LookupDispatchAction必须重写getKeyMethodMap方法,该方法返回一个Map 对象, 并在该对象内保存了按钮标题与方法之间的对应。 4使用ForwardAction 如果需要从一个页面或资源转换到另一个资源时,直接使用页面或资源路径的超级链接定位并不是好的做法,这使得控制器没有机会处理相关的请求事直。使用ForwardAction可以完成请求的转发,当控制器调用ForwardAction的performO方法时,它会使用属性parameter 所设定的路径进行forward 的动作。下面是一个设定ForwardAction的例子:
<actlon-mapplngs> <action path="/welcome" type="org.apache.struts.actions.ForwardAction" parameter="/welcome.jsp"/> </action-mappings> 该action 仅仅完成转发,并没有执行其他的额外动作。 页面控制转发的代码如下: <a href="welcome.do">转入</a> 当单击转入超级链接时,将可以转向ForwardAction中parameter指向的资源。 5使用IncludeAction IncludeAction的用法与ForwardAction的用法比较相似,区别在于ForwardAction将 跳转到action 定义的资源,而IncludeAction用于引入该action 对应的资源。 下面是IncludeAction定义的源代码: <actio口-mapplngs> <action path="/welcome" type="org.apache. struts.actions. IncludeAction" parameter="/welcome.jsp"/> </action-mappings>该action 用于经welcome.jsp 作为资源导入。
页面中负责加载该action 所导入资源的代码如下: <jsp:include page="welcome.do"/><br>上面的代码将会把welcome action 定义的资源导入该页面。 6使用SwitchAction SwitchAction 主要用于模块之间的切换。当一个应用之中存在多个模块时,使用 SwitchAction在不同模块之间的action 之间切换还是相当方便的。 在下面的web.xml 中,力日载了Struts 的两个配置文件,其中一个作为系统的一个模块加载,该web.xml 的配置代码如下: <servlet> <! 定义Struts 的核心控制器--> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <'一指定Struts 的第一个配置文件--> <lnlt-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-con工fg.xml</param-value> </Inilt-param> <!一指定Struts 的第二个配置文件,作为wawa 模块配置一〉 <lnlt-param> <param-name>config/wawa</param-name> <param-value>/WEB-INF/struts-configl.xml</param-value> </Init-param> <load-on-startup>2</load-on-startup> </servlet> 该应用包括了一个wawa 的模块,并在struts-config1.xml 文件中配置一个action,该action 的配置代码如下: <action-mappings> <action path="/welcome" forward="/welcome.jsp"/> </action-mappings> 该action 的定义非常简单,仅完成页面的转向。如果现在需要从应用的页面请求该action,可以使用如下SwitchAction。 定义SwitchAction也相当简单,只需要定义path、type 属性即可。下面是SwitchAction的定义代码: <action-mappings> <action path="/moduleSwitch" type="org.apache.struts.actions.SwithcActio丑"/> </action-mappings> 在使用SwitchAction 时,必须在请求中带两个参数:第一个是prefix,用来指定模块宅称:另一个是page,用来指定相模块中的资源路径。下面是页面中超级链接对wawa模块的welcome action 请求,页面的超级链接代码如下: <a href=咄oduleSwitch.do?prefix=/wawa&page=/welcome.do转">入另一个模块</a>上面的超级链接地址中,/wawa是模块名,而page对应wawa模块下的welcome的actiono