技术开发 频道

将Struts应用迁移到Struts 2(二)



在我们调用action之前,我们必须通过XML配置文件去配置它们。
    在Struts中, 我们习惯用在WEB-INF 目录的"struts-config.xml"配置文件,在这里我们需要配置action form和action属性。在Struts2中, 用的是在classpath中的"struts.xml"配置文件, 它看起来好象会稍微复杂一些,因为它需要在配置action的同时也配置其拦截器。

在Struts中配置 form-beans 节点很容易, 只需要一个唯一的名字,还有就是继承ActionForm类的class作为type。


<struts-config> <form-beans> <form-bean name="blogForm" type="com.fdar.articles.infoq.conversion.struts.BlogForm"/> </form-beans> ... </struts-config>
在我们的例子中,我们的配置文件有3点不相同:
1. 重定向配置
    在Struts的配置中,每个mapping 都需要提供调用action时所需要对应的路径,Struts默认为".do", 例如paht是"/struts/add"对应于URL"/struts/add.do"。同时也需要一个forward 属性来提供给URL去转向,如"/struts/add.jsp".
<struts-config> ... <action-mappings> <action path="/struts/add" forward="/struts/add.jsp"/> ... </action-mappings> </struts-config>

而Struts2的需要更多的一些配置,如:

首先你会注意到的是,代替action-mappings 节点的是includepackage 节点。Struts2可以把配置细分到任意数目的配置文件中,来实现配置可模块化管理。每个配置文件的结构其实都是一样的,不同的只是文件名。
    include 节点中,以文件名作为file 属性,可把所include的文件内容包含到当前文件中。
   package 节点把actions组成一组,其name 属性的值必须是唯一的。
   在 Struts action的配置中, paht属性需要指定完整的URL路径。而在Struts2中,URL是通过package节点中的namespace属性,还有在action 节点中的name 属性, 和action扩展(默认是".action")共同起作用的。在上面的例子中,则URL为"/struts2/add.action"时会调用action。
   package节点除了可以分离命名空间外, package 节点中的 extends 属性,还提供了某种可复合的组成结构。通过继承另外一个package节点,你就能继承那个节点的配置,包括其actions, results, interceptors, exception,等值。在我们的例子中,"struts2" package节点继承了 "struts-default" package 节点(在"struts-default.xml" 文件里定义了该节点) ,注意这个是主要的include文件,所以必须在所有配置之前的第一行中写出。 这个功能有助于大大减少你重复性输入默认配置所浪费的时间。
    最后是result 节点, 它只是存放你这个action所需要转向的URL. 在这里我们没有提及nametype 属性。如果你不想改变它们的默认属性的话,你能忽略不写它们,让你的配置文件看起来更清晰。从action返回的 "success" 的结果将组成这个JSP显示给用户。


2. Action 配置
    在Struts 中forward 节点指定了action处理后,结果将重定向到哪个相应的页面。type属性指定了action的类,scope 属性保证了form beans只在request范围内。
<struts-config> ... <action-mappings> <action path="/struts/list" scope="request" type="com.fdar.articles.infoq.conversion.struts.ListBlogsAction" > <forward name="success" path="/struts/list.jsp"/> </action> ... </action-mappings> </struts-config>


Struts2 的 XML配置和上面提到的基本相同。唯一不同的就是通过class属性为action节点提供了它所需要调用的类的完整路径
<struts> ... <package name="struts2" extends="struts-default" namespace="/struts2"> <default-interceptor-ref name="defaultStack"/> <action name="list" class="com.fdar.articles.infoq.conversion.struts2.ListBlogsAction"> <result>/struts2/list.jsp</result> <interceptor-ref name="basicStack"/> </action> ... </package> </struts>


如果是用其他的方法而不是用默认的execute 方法去调用action(在BlogAction 类中大多数方法如此), 则需要在action节点的 method 属性里加入方法名,下面就是个例子,这时候update方法将会被调用。
<action name="update" method="update" class="com.fdar.articles.infoq.conversion.struts2.BlogAction" > ... </action>


default-interceptor-refinterceptor-ref 节点有几点不同。在第一篇文章中,我们看到在action被调用之前必须通过一系列的拦截器,而这两个节点就是用来配置拦截器组的。default-interceptor-ref 节点为该package提供了默认的拦截器组。当在action节点中提供 interceptor-ref节点时 ,它就会覆盖默认的拦截器(interceptor-ref 节点能够和单独一个拦截器相关联,或者跟一个拦截器组相关联),在action节点中可以存在多个interceptor-ref节点,处理拦截器组的顺序会和该节点列出的顺序一致。


3. 再重定向配置
    当我们提交表格的时候,我们需要重定向到更新后的结果页面。这个通常称为 "post-redirect pattern" 或, 最近出现的, "flash scope."
    由于这是一个form, 所以在Struts中我们需要为Struts指定一个ActionForm。需要在name属性中提供form的名称,同样地,我们也需要在forward 节点中举加入redirect属性为true。
<struts-config> ... <action-mappings> <action path="/struts/save" type="com.fdar.articles.infoq.conversion.struts.SaveBlogEntryAction" name="blogForm" scope="request"> <forward name="success" redirect="true" path="/struts/list.do"/> </action> ... </action-mappings> </struts-config>


Struts2 在result 节点里提供了type 属性, 默认情况下是"dispatch", 如果需要重定向,则需要设为 "redirect"。
<struts> ... <package name="struts2" extends="struts-default" namespace="/struts2"> <action name="save" method="save" class="com.fdar.articles.infoq.conversion.struts2.BlogAction" > <result type="redirect">list.action</result> <interceptor-ref name="defaultStack"/> </action> ... </package> </struts>



总结
    我们并不可能在这篇文章中覆盖所有的内容,如果你需要更好的了解整个框架,还有其他的实现方式和选项,这里有几点可以供你参考:


  • 配置拦截器和拦截器组 - 以Struts2-core JAR 包里的"struts-default.xml" 文件作为例子。"struts-default.xml" 演示了如何配置你自己的拦截器组,包含新的拦截器,你可以尝试实现自己的拦截器。
  • 配置文件中的通配符模式 - 你可以选择使用Struts2中的通配符模式来简化你的配置。
  • 通过 ParameterAware 接口把form值传入maps中 - 你可以在Struct2中配置,让所有request的form属性都存于action的一个map中,这样就不需要专门再为action指定model / transfer / value object了。这和Struts的dynamic form特点很相似。
    也许到现在为,也许你有个疑问,"迁移后我们的界面是否可以完全重用呢?",答案是yes。你能从这里, 下载到我这篇文章中的完整源代码,你可以自己尝试把URL的扩展名由".do" 改为 ".action",使用的页面时一样的。除此之外,其实用JSTL来代替Struts taglib也是很容易的。
0
相关文章