Spring和Struts整合的价值在于将Struts使用的BO或DAO 乃至Action交给Spring管理,从而充分利用Spring强大的IoC和AOP 特性。
无论使用哪种方式整合,都需要为 Struts装载 Spring 应用上下文环境。有以下三种方式:
1) 在struts-config.xml中使用Struts Plugin
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/classes/applicationContext.xml,/WEB-INF/action-servlet.xml"/>
</plug-in>
2) 在web.xml中使用ContextLoaderListener
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
3) 在web.xml中使用ContextLoaderServlet
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringContextServlet</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
注意:
用Struts PlugIn的方式加载Spring配置文件有可能导致DWR无法取得Spring中定义的bean,因为DWR有可能先于Struts被访问使用,而此时Struts配置文件还未加载!
因此,在Spring、Struts和DWR 集成时,应该在web.xml中通过ContextLoaderLisenter或ContextLoaderServlet加载Spring配置文件。
最佳实践是使用Struts PlugIn的方式加载Struts Action配置文件/WEB-INF/action-servlet.xml,而使用ContextLoaderLisenter或ContextLoaderServlet方式加载Spring配置文件applicationContext.xml,通过两次加载完成Spring所有配置文件的加载。
至少有四种Spring与Struts整合方式:
1. 手工创建Spring 环境整合 Spring和Struts
为了Web应用环境可以和Spring的IoC容器很好的结合,Spring提供了专门用于Web应用
环境中的Spring容器——WebApplicationContext。使用ContextLoaderPlugIn装载 Spring 应
用程序环境时,ContextLoaderPlugIn会自动创建一个WebApplicationContext对象,并加载
相应的配置文件,然后将其保存在ServletContext中。之后所有的Servlet或Action便都可以过
ServletContext访问该WebApplicationContext实例并从中获取BO或DAO Bean。
ServletContext servletContext=this.getServlet().getServletContext();
WebApplicationContext ctx=
WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserInfoDAO userInfoDAO=(UserInfoDAO)ctx.getBean("userInfoDAO");
2. 使用 Spring 的 ActionSupport 类整合 Struts
org.springframework.web.struts.ActionSupport 类提供了一个 getWebApplicationContext() 方法可以获取到WebApplicationContext实例,您所做的只是从 Spring 的 ActionSupport 而不是 Struts Action 类扩展您的动作:
public class AddActionSupport extends ActionSupport {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
AddForm addForm = (AddForm) form;
UserInfo user=new UserInfo();
user.setUserName(addForm.getName());
user.setUserPwd(addForm.getPassword());
UserInfoDAO userInfoDAO=
(UserInfoDAO)getWebApplicationContext().getBean("userInfoDAO");
userInfoDAO.save(user);
return mapping.findForward("success");
}
}
结论:第1、2种整合方式由Spring来管理BO或DAO Bean,实现了表示层和业务逻辑层的解耦,但Struts的Action和Spring耦合在了一起,违反了Spring“非侵入”性原则;另外,Action类负责查找由Spring管理的Bean,也违背了Spring控制反转(IoC)的原则。以下第3、4种整合方式实现了由Spring来管理Struts Action,实现了Struts和Spring的解耦,从而解决了以上问题。
3. 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor
用Spring的DelegatingRequestProcessor重载Struts 默认的 RequestProcessor。这样当收到一个针对Action的请求时,DelegatingRequestProcessor会自动从Spring Context中查找对应的Action Bean。
在struts-config.xml中添加:
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
4. 【最佳方案】使用DelegatingActionProxy将Struts Action 管理全权委托给 Spring 框架
Action 的创建和对象的依赖注入全部由IOC容器来完成,使用Spring的DelegatingAcionProxy来帮助
实现代理的工作。DelegatingActiongProxy继承于org.apache.struts.action.Action 。此时需要将struts-
config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="error" path="/error.html" />
<forward name="success" path="/success.html" />
</action>
3、4两种方式都需要在WEB-INF下新建一个action-servlet.xml作为Spring context文件,创建Struts Action Bean,并对Action进行BO或DAO Bean注入:
<!--name 的取值一定要和Struts 配置文件action 中的path 的值相对应-->
<bean name="/login" class="cn.qdqn.ssh.struts.action.LoginAction">
<property name="userBO">
<ref bean="userBO"/>
</property>
</bean>
结论:
以上2种方式实现了由Spring管理Struts的Action,从而可以利用Spring在Struts Action中轻松的注入BO或DAO,还可以将 Spring 的 AOP 拦截器应用于Struts 动作,用最小的代价处理横切关注点。
第3种整合方式只需要配置一个<controller>,不需要改动Struts Action配置信息,但Struts的 RequestProcessor只能被重载一次,如果在应用中还要进行编码等其它功能RequestProcessor重载时,此种方式将异常繁琐。
第4种整合方式可以避免RequestProcessor的占用,但必须将struts-config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy。
无论使用哪种方式整合,都需要为 Struts装载 Spring 应用上下文环境。有以下三种方式:
1) 在struts-config.xml中使用Struts Plugin
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/classes/applicationContext.xml,/WEB-INF/action-servlet.xml"/>
</plug-in>
2) 在web.xml中使用ContextLoaderListener
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
3) 在web.xml中使用ContextLoaderServlet
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringContextServlet</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
注意:
用Struts PlugIn的方式加载Spring配置文件有可能导致DWR无法取得Spring中定义的bean,因为DWR有可能先于Struts被访问使用,而此时Struts配置文件还未加载!
因此,在Spring、Struts和DWR 集成时,应该在web.xml中通过ContextLoaderLisenter或ContextLoaderServlet加载Spring配置文件。
最佳实践是使用Struts PlugIn的方式加载Struts Action配置文件/WEB-INF/action-servlet.xml,而使用ContextLoaderLisenter或ContextLoaderServlet方式加载Spring配置文件applicationContext.xml,通过两次加载完成Spring所有配置文件的加载。
至少有四种Spring与Struts整合方式:
1. 手工创建Spring 环境整合 Spring和Struts
为了Web应用环境可以和Spring的IoC容器很好的结合,Spring提供了专门用于Web应用
环境中的Spring容器——WebApplicationContext。使用ContextLoaderPlugIn装载 Spring 应
用程序环境时,ContextLoaderPlugIn会自动创建一个WebApplicationContext对象,并加载
相应的配置文件,然后将其保存在ServletContext中。之后所有的Servlet或Action便都可以过
ServletContext访问该WebApplicationContext实例并从中获取BO或DAO Bean。
ServletContext servletContext=this.getServlet().getServletContext();
WebApplicationContext ctx=
WebApplicationContextUtils.getWebApplicationContext(servletContext);
UserInfoDAO userInfoDAO=(UserInfoDAO)ctx.getBean("userInfoDAO");
2. 使用 Spring 的 ActionSupport 类整合 Struts
org.springframework.web.struts.ActionSupport 类提供了一个 getWebApplicationContext() 方法可以获取到WebApplicationContext实例,您所做的只是从 Spring 的 ActionSupport 而不是 Struts Action 类扩展您的动作:
public class AddActionSupport extends ActionSupport {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
AddForm addForm = (AddForm) form;
UserInfo user=new UserInfo();
user.setUserName(addForm.getName());
user.setUserPwd(addForm.getPassword());
UserInfoDAO userInfoDAO=
(UserInfoDAO)getWebApplicationContext().getBean("userInfoDAO");
userInfoDAO.save(user);
return mapping.findForward("success");
}
}
结论:第1、2种整合方式由Spring来管理BO或DAO Bean,实现了表示层和业务逻辑层的解耦,但Struts的Action和Spring耦合在了一起,违反了Spring“非侵入”性原则;另外,Action类负责查找由Spring管理的Bean,也违背了Spring控制反转(IoC)的原则。以下第3、4种整合方式实现了由Spring来管理Struts Action,实现了Struts和Spring的解耦,从而解决了以上问题。
3. 使用 Spring 的 DelegatingRequestProcessor 覆盖 Struts 的 RequestProcessor
用Spring的DelegatingRequestProcessor重载Struts 默认的 RequestProcessor。这样当收到一个针对Action的请求时,DelegatingRequestProcessor会自动从Spring Context中查找对应的Action Bean。
在struts-config.xml中添加:
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
4. 【最佳方案】使用DelegatingActionProxy将Struts Action 管理全权委托给 Spring 框架
Action 的创建和对象的依赖注入全部由IOC容器来完成,使用Spring的DelegatingAcionProxy来帮助
实现代理的工作。DelegatingActiongProxy继承于org.apache.struts.action.Action 。此时需要将struts-
config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy:
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy">
<forward name="error" path="/error.html" />
<forward name="success" path="/success.html" />
</action>
3、4两种方式都需要在WEB-INF下新建一个action-servlet.xml作为Spring context文件,创建Struts Action Bean,并对Action进行BO或DAO Bean注入:
<!--name 的取值一定要和Struts 配置文件action 中的path 的值相对应-->
<bean name="/login" class="cn.qdqn.ssh.struts.action.LoginAction">
<property name="userBO">
<ref bean="userBO"/>
</property>
</bean>
结论:
以上2种方式实现了由Spring管理Struts的Action,从而可以利用Spring在Struts Action中轻松的注入BO或DAO,还可以将 Spring 的 AOP 拦截器应用于Struts 动作,用最小的代价处理横切关注点。
第3种整合方式只需要配置一个<controller>,不需要改动Struts Action配置信息,但Struts的 RequestProcessor只能被重载一次,如果在应用中还要进行编码等其它功能RequestProcessor重载时,此种方式将异常繁琐。
第4种整合方式可以避免RequestProcessor的占用,但必须将struts-config.xml中所有Action类别全部配置为 org.springframework.web.struts.DelegatingActionProxy。