一、集成时需要考虑的问题:
Spring与第三方MVC框架集成时,需要考虑的问题是如何在第三方MVC框架中访问Spring IOC容器管理的Bean,或者说,如何获取Spring IOC容器的实例。我们还要保证在第三方MVC框架开始处理用户请求之前,Spring的IOC容器必须初始化完毕。
二、自动加载Spring的IOC容器的两种方式
1、利用第三方框架的扩展点,实现加载Spring的IOC容器,例如,Struts就提供了Plugin扩展。
2、第二种方式是在web.xml中定义Lisenter或Servlet,让Web应用程序一启动就自动加载Spring的IOC容器。这种方式较为通用,对于一些不太常见的第三方MVC框架也可以用这种方式来尝试与Spring集成。
这里需要注意,如果正在使用基于Servlet 2.3或更高规范的Web服务器,则应当使用Spring提供的ContextLoaderListener来加载IOC容器,因为根据Servlet2.3规范,所有的Listener都会在Servlet被初始化之前完成初始化。由于我们希望尽可能早地完成Spring IOC容器的初始化,因此采用ContextLoaderListener加载Spring的Ioc容器是最适合的,这时在web.xml中定义如下:
...
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
...
默认的,ContextLoaderListener会在/WEB-INF/目录下查找名为applicationContext.xml文件,作为Spring的XML配置文件加载。如果使用其他文件名,或者有多个XML配置文件,就需要预先在web.xml文件中的<context-param>标签中指定。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/spring/applicationContext.xml
/WEB-INF/config/spring/datasource.xml
/WEB-INF/config/spring/serviceBean.xml
/WEB-INF/config/spring/actionBean.xml
</param-value>
</context-param>
如果正在使用的Web服务器还不支持Servlet 2.3规范,则无法使用Listener,也就无法通过ContextLoaderListener来加载Spring的IOC容器。为些Spring提供了另一个ContextLoaderServlet来加载Spring的IOC容器。
<servlet>
<servlet-name>SpringContextServlet</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
由于必须加载ContextLoaderServlet,然后再加载其他的Servlet,才能保证Spring的IoC容器在其他Servlet处理用户请求之前初始化完毕,因此,需设置<load-on-startup>为0,表示Web服务器一启动就加载ContextLoaderServlet,其他的Servlet的<load-on-startup>值应设得大一些,保证ContextLoaderServlet有足够的时间初始化Spring的IOC容器。
一旦完成了Spring IOC容器的加载,就可以通过Spring提供的一个辅助类WebApplicationContextUtils来获得Spring IOC容器的实例了。
ApplicationContext ctx=
WebApplicationContextUtils.getWebApplicationContext(servlet.getServletContext());
三、Spring与Struts的集成
方式一:
第一种方案是通过Spring提供的一个Struts插件来初始化IOC容器,然后从Spring提供的ActionSupport派生所有的Aciton,以便能通过 getWebApplicationContext获得Spring IOC容器中所有Bean的实例。
1、 在Struts配置文件的最后添加Spring插件声明:
<struts-config>
<plug-in className=”org.springframework.web.struts.ContextLoaderPlugIn”/>
</struts-config >
然后设计一个BaseAction,其中定义了获得业务逻辑接口的方法,其他所有的Action都从BaseAction派生即可非常方便地调用业务逻辑接口,比如。
public class BaseAction extends ActionSupport{
public Object getBean(String beanName){
return (Object) getWebApplicationContext().getBean(beanName);
}
}
这样,BaseAction就可以随时通过Spring的ApplicationContext获得逻辑组件的引用,所有的Action子类都可以直接通过getBean(String beanName)获得指定组件。
最后一步是编写Spring的XML配置文件,在此配置文件中定义所有的Bean组件,但不包括Struts的Action实例。
<beans>
<bean name="userService" class="com.springTest.UserServiceImpl"
</bean>
...
</beans>
如果Spring的XML配置文件没有使用默认的文件名,就必须在Struts配置文件中声明Plugin时指定文件位置。
<struts-config>
<plug-in className=”org.springframework.web.struts.ContextLoaderPlugIn”>
<set-property property="contextConfigLocation" value="/WEB-INF/config/spring/mySpringConfig.xml "/>
</plug-in>
</struts-config >
这种方式集成Spring和Struts时,如果合理地抽象出一个类似BaseAction的类作为所有Action类的超类,在集成到Spring时,只需将BaseAction的超类从Struts的Action类改为Spring提供的ActionSupport,然后在Struts中声明Spring的Plugin,就可以在不修改任何Action的情况下实现和Spring的集成。
方式二:
第二种集成Struts的方案是将Struts的所有Action都作为Spring IOC容器中的Bean来管理,然后通过Spring提供的DelegatingRequestProcessor来替代Struts的默认派发器,以便让Spring能截获派发给Action的请求。在这种方式下,业务逻辑组件通过依赖注入的方式在Spring的IOC容器中就配置完毕了。
设计一个BaseAction,其中定义了获得业务逻辑接口的方法,其他所有的Action都从BaseAction派生即可非常方便地调用业务逻辑接口,比如。
public class BaseAction extends Action{
private UserService userService;
public void setUserService(UserService userService){
this.userService=userService;
}
public UserService getUserService(){
return userService;
}
}
在Struts配置文件的最后添加Spring提供的DelegatingRequestProcessor和插件声明:
<struts-config>
...
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn" />
</struts-config >
Spring提供的Struts插件仍负责启动Spring容器,而DelegatingRequestProcessor可以让Spring接管请求,从而将请求派发到IOC容器管理的Action实例。为此,在Spring的XML配置文件中,除了定义业务逻辑和其他组件外,还必须声明每一个Action类,其name属性和Struts配置文件中的path要完全一致。假设在Struts配置文件中配置了两个Action:
<action-mappings>
<action path="/login" type="com.struts.LoginAction"
name="loginForm" scope="request" validate="true" input="/login.jsp">
<forward name="success" path="/hello.jsp" />
<forward name="failure" path="/login.jsp" />
</action>
<action path="/logout" type="com.struts.LogoutAction">
<forward name="success" path="/login.jsp" />
</action>
</action-mappings>
则在Spring的配置文件中,除了定义UserService组件外,还必须定义两个Action,并且要和Struts配置文件中的Action一一对应。
<bean id="userService" class="com.testSpring.UserServiceImpl" />
<bean name="/login" class="com.struts.LoginAction">
<property name="userService" ref="userService" />
</bean>
<bean name="/logout" class="com.struts.LogoutAction">
<property name="userService" ref="userService" />
</bean>