Spring整合Struts的三种方法
无论使用那种方法,都必须先装载环境.即在Struts配置文件中加入:
<plug-in className= "org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
使用 Spring 的 ContextLoaderPlugin 为 Struts 的 ActionServlet 装载 Spring 应用程序环境。
方法如下:
- 使用 Spring 的 ActionSupport 类整合 Structs
- 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor
- 将 Struts Action 管理委托给 Spring 框架
方法一 : 使用 Spring 的 ActionSupport 类整合 Structs
从Action类下手,就是新建一个Action让它派生自Spring中org.springframework.web.struts.ActionSupport类,而不是Struts的Action类.Spring的ActionSupport类提供了一种简便的方法 getWebApplicationContext().
代码片段: public class MyAction extends ActionSupport{
public ActionForward excute(........){
.......
}
ApplicationContext ctx = getWebApplicationContext();
BookService bookService = (BookService) ctx.getBean("bookService");
..............
通过派生Spring的ActionSupport而不是Struts的Action,创建一个新的Action.
getWebApplicationContext() 方法获得一个 ApplicationContext.
然后查找一个Bean.
缺点:
它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring,那么您必须重写代码。并且,由于Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时,这种技术可能有用,但是在大多数情况下,这种方法不如另外两种方法合适。
方法二: 覆盖 Struts 的 RequestProcessor
使用 org.springframework.web.struts.DelegatingRequestProcessor 类来覆盖
Struts 的 RequestProcessor 处理程序
代码片段: (struts配置文件)
<controller processorClass="org.springframework.web.struts. DelegatingRequestProcessor"/>
然后在Spring的配置文件中注册动作:
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit" <!-- 使用name属性以匹配struts的动作名称 -->
class="ca.nexcel.books.actions.SearchSubmit"><property name="bookService">
<ref bean="bookService"/>
</property>
</bean>优点:
这种设计使 Struts 动作并不知道它正被 Spring 管理,并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在,所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring.
缺点:
如果您使用一个不同的 RequestProcessor,则需要手动整合 Spring 的 DelegatingRequestProcessor。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。这种改变将会对这种解决方法的使用寿命造成负面的影响。
方法三: 将动作管理委托给 Spring
一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 struts-config 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作的 JavaBean 属性,并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。
代码片段:
<action-mappings>
<action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/>
<action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/>
<action path="/searchSubmit"
type="org.springframework.web.struts.DelegatingActionProxy" <!--Here-->input="/searchEntry.do"
validate="true"
name="searchForm">
<forward name="success" path="/WEB-INF/pages/detail.jsp"/>
<forward name="failure" path="/WEB-INF/pages/search.jsp"/>
</action>
</action-mappings>.....
<plug-in
className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/>
</plug-in>
Spring 环境中注册一个 Struts 动作:
<bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/>
<bean name="/searchSubmit"
class="ca.nexcel.books.actions.SearchSubmit">
<property name="bookService">
<ref bean="bookService"/>
</property>
</bean>
优点:
动作委托解决方法是这三种方法中最好的。Struts 动作不了解 Spring,不对代码作任何改变就可用于非 Spring 应用程序中。RequestProcessor 的改变不会影响它,并且它可以利用 Spring AOP 特性的优点。
一旦让 Spring 控制您的 Struts 动作,您就可以使用 Spring 给动作补充更强的活力。例如,没有 Spring 的话,所有的 Struts 动作都必须是线程安全的。如果您设置 <bean> 标记的 singleton 属性为“false”,那么不管用何种方法,您的应用程序都将在每一个请求上有一个新生成的动作对象。您可能不需要这种特性,但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如,当实例化 Struts 动作时,<bean> 标记的 init-method 属性被用于运行一个方法。类似地,在从容器中删除 bean 之前,destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法,它们以一种与 Servlet 生命周期相同的方式进行管理。