假设我们使用的是tomcat服务器
在服务器启动时,如果我们想在struts的action中使用spring容器里的bean,
那么必须要在启动时建立好spring的容器。要实现这,一般有两种方法
·让MVC 框架负责创建ApplicationContext 实例,并在MVC 框架加载时自动创建
Spring 容器。Struts 就是采用这种机制与Spring 整合。
·在web.xml 文件中加载Spring 容器,这是最常见的做法。Spring 自己的MVC 框
架就是采用这种策略。
关于让MVC 框架负责创建ApplicationContext 实例的情况比较多,因为每个MVC
框架的启动机制有区别,因此加载ApplicationContext 的方式也各有不同。
对于在web.xml 配置文件中配置ApplicationContext 的自动创建有两种策略:
·.利用ServletContextListener 实现。
·采用load-on-startup Servlet 实现。
**********利用ServletContextListener 实现**************
在web.xml中增加
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
这个listener会自动在WEB-INF目录下寻找applicationContext.xml并初始化容器
如果spring的配置文件有多个的话,则还要增加如下标签
<context-param>
<1-- 参数名为contextConfigLocation--〉
<param-name>contextConfigLocation</param-name>
<!一多个配置文件之间以,隔开--〉
<param-value>/WEB-工NF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>
*******************采用load-on-startup Servlet 实现****************
在web.xml中增加
<servlet>
<servlet-name>context</servlet- name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>l</load-on-startup>
</servlet>
为了让ContextLoaderServlet 随应用启动而启动,应将此Servlet 配置成
load-on-startup 的Servleto load-on-startup 的值小一点比较合适,因为要保证ApplicationContext 优先创建。
同样,如果是采用多个配置文件的话,需要加入
<context-param>
<1-- 参数名为contextConfigLocation--〉
<param-name>contextConfigLocation</param-name>
<!一多个配置文件之间以,隔开--〉
<param-value>/WEB-工NF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>
******************让struts创建spring容器********************
Struts 中提供了PlugIn 的扩展点,可在应用启动和关闭时,创建或销毁某些资源。
Spring 的Contex tLoaderP1ugIn 类,该类实现org.apache.struts.action.P1ugIn 接口,用于在启动时加载某个模块。
ContextLoaderPlugin 默认加载的配置文为servletName-servelet.xrnl。其中servletName
是Struts 的ActionServlet 对应的Servlet 名。例如web.xrnl 中进行如下定义:
<servlet>
<servlet-name>actionSevlet</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
ContextLoaderPlugin 默认加载\WEB-INF\actionSevlet-servlet.xrnl,将该文件作为
Spring 的配置文件。因此,如果Spring 的配置文件只有一个,且文件名为
actionSevlet-servlet. xml ,则只需在Struts 配置文件中增加如下代码:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugln"/>
如果有多个配置文件,或者配置文件的文件名不符合规则,则可以采用" contextConfig
Location" 属性载入。同样,在多个配置文件之间以","隔开。下面是载入多个配置文
件配置代码:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugln">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml, /WEB-INF/applicationContext.xml"/>
</plug-in〉
创建了ApplicationContext 实例后,关键是如何将ActionServlet 拦截的请求,转发给
Spring 管理的bean
由于SpringIoC 容器不仅管理本身的业务bean ,还负责管理Struts 的Action 。因此,
需要让ActionServlet 将请求不再转发给struts-config.xrnl 配置的action ,而是转发给
ApplicationContext 里配置的bean 。
ActionServlet 将请求转发到Spring 容器,有以下两个时机。
·在ActionServlet 之处将处理转发给Spring 容器中的bean
.在Action 之处将处理转发给Spring 容器中的bean
根据这两个时机,完成这个转发也有以下两种策略。
·采用DelegatingRequestProcessor ,在ActionServlet 处完成转发。
·采用DelegatingActionProxy ,在Action 处完成转发。
****************采用DelegatingRequestProcessor *****************
在struts-config.xml文件中
去掉每个action中的type属性
增加
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
acton-servlet. xml 用于配置表现层context,其详细配置信息如下:
<?xml version="1.0" encoding="gb2312"?>
<!-- 指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-//SPR工NG//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd">
<!-- spring 配置文件的根元素一〉
<beans>
<!一每个request 请求产生新实例,所以将action 配置成non-singleton-->
<bean name="/login" class="lee.LoginAction" singleton="false">
<!一配置依赖注入-->
<property name="vb">
<!-- 引用容器中另外的bean-->
.......
</property>
</bean>
</beans>
由于每次请求时,都应该启动新的action 来处理用户请求,因此应将action bean 配
置成non-singleton行为。
注意: ActionServlet转发请求时,是根据bean 的name 属性,而不是id 属性。因此,
此处确定的name 属性应与Struts 的action 属性相同。
*******************采用DelegatingActionProxy **********************
与上面的方法相比,本方法只是稍作修改如下:
在struts-config.xml文件中
所有的action的type修改为:type="org.springframework.web.struts.DelegatingActionProxy"
去掉
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
就可以了
DelegatingActionProxy 接受ActionServlet 转发过来的请求,然后转发给
ApplicationContext管理的bean,这是典型的链式处理。
通过配置文件可看出,在struts-config.xml文件中配置了大量DelegatingActionProxy
实例, Spring 容器中也配置了同名的Action。即Struts 的业务控制器分成了两个部分:
第一个部分是Spring 的DelegatingActionProxy,这个部分没有实际意义,仅仅完成转发:
第二个部分是用户的Action 实现类,负责实际的处理工作。
这种策略的性能比前一种的策略要差一些,因为需要多创建一个DelegatingActionProxy
实例。而且在J2EE 应用中的Action 非常多,这将导致需要大量创建DelegatingActionProxy
实例,在使用一次之后,要等待垃圾回收机制回收,从而降低了其性能。
如果想struts不受spring容器的管理,而又要在action中使用spring容器中的bean的话
,我们可以在action中手动获得ApplicationContext 实例。在这种整合策略下, Struts 的Action 不接受IoC 容器管理,使Action 的代码与Spring API 部分耦合,这种策略也有其好处:代码的可读性非常强,在Action 的代码中显式调用业务逻辑组件时,无须等待容器注入。
在Action 中访问ApplicationContext 有以下两种方法:
·利用WebApplicationContextUtils 工具类。
·利用ActionSupport 支持类。
不过,这会造成很多冗余代码,在每个action中都要增加获取applicationContext的代码
有一种折中的办法就是实现一个BaseAction
//BaseAction 继承ActionSupport 类
public class BaseAction extends ActionSupport
{
public Object getBean(String beanName){
return getWebApplicationContext() .getBean(beanName);
}
}
然后每个action类都继承这个类,要使用spring容器中的bean时,直接使用
getBean()函数就可以了
很好地实现了控制层与业务逻辑层的分离
在服务器启动时,如果我们想在struts的action中使用spring容器里的bean,
那么必须要在启动时建立好spring的容器。要实现这,一般有两种方法
·让MVC 框架负责创建ApplicationContext 实例,并在MVC 框架加载时自动创建
Spring 容器。Struts 就是采用这种机制与Spring 整合。
·在web.xml 文件中加载Spring 容器,这是最常见的做法。Spring 自己的MVC 框
架就是采用这种策略。
关于让MVC 框架负责创建ApplicationContext 实例的情况比较多,因为每个MVC
框架的启动机制有区别,因此加载ApplicationContext 的方式也各有不同。
对于在web.xml 配置文件中配置ApplicationContext 的自动创建有两种策略:
·.利用ServletContextListener 实现。
·采用load-on-startup Servlet 实现。
**********利用ServletContextListener 实现**************
在web.xml中增加
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
这个listener会自动在WEB-INF目录下寻找applicationContext.xml并初始化容器
如果spring的配置文件有多个的话,则还要增加如下标签
<context-param>
<1-- 参数名为contextConfigLocation--〉
<param-name>contextConfigLocation</param-name>
<!一多个配置文件之间以,隔开--〉
<param-value>/WEB-工NF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>
*******************采用load-on-startup Servlet 实现****************
在web.xml中增加
<servlet>
<servlet-name>context</servlet- name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>l</load-on-startup>
</servlet>
为了让ContextLoaderServlet 随应用启动而启动,应将此Servlet 配置成
load-on-startup 的Servleto load-on-startup 的值小一点比较合适,因为要保证ApplicationContext 优先创建。
同样,如果是采用多个配置文件的话,需要加入
<context-param>
<1-- 参数名为contextConfigLocation--〉
<param-name>contextConfigLocation</param-name>
<!一多个配置文件之间以,隔开--〉
<param-value>/WEB-工NF/daoContext.xml,/WEB-INF/applicationContext.xml</param-value>
</context-param>
******************让struts创建spring容器********************
Struts 中提供了PlugIn 的扩展点,可在应用启动和关闭时,创建或销毁某些资源。
Spring 的Contex tLoaderP1ugIn 类,该类实现org.apache.struts.action.P1ugIn 接口,用于在启动时加载某个模块。
ContextLoaderPlugin 默认加载的配置文为servletName-servelet.xrnl。其中servletName
是Struts 的ActionServlet 对应的Servlet 名。例如web.xrnl 中进行如下定义:
<servlet>
<servlet-name>actionSevlet</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
ContextLoaderPlugin 默认加载\WEB-INF\actionSevlet-servlet.xrnl,将该文件作为
Spring 的配置文件。因此,如果Spring 的配置文件只有一个,且文件名为
actionSevlet-servlet. xml ,则只需在Struts 配置文件中增加如下代码:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugln"/>
如果有多个配置文件,或者配置文件的文件名不符合规则,则可以采用" contextConfig
Location" 属性载入。同样,在多个配置文件之间以","隔开。下面是载入多个配置文
件配置代码:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugln">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml, /WEB-INF/applicationContext.xml"/>
</plug-in〉
创建了ApplicationContext 实例后,关键是如何将ActionServlet 拦截的请求,转发给
Spring 管理的bean
由于SpringIoC 容器不仅管理本身的业务bean ,还负责管理Struts 的Action 。因此,
需要让ActionServlet 将请求不再转发给struts-config.xrnl 配置的action ,而是转发给
ApplicationContext 里配置的bean 。
ActionServlet 将请求转发到Spring 容器,有以下两个时机。
·在ActionServlet 之处将处理转发给Spring 容器中的bean
.在Action 之处将处理转发给Spring 容器中的bean
根据这两个时机,完成这个转发也有以下两种策略。
·采用DelegatingRequestProcessor ,在ActionServlet 处完成转发。
·采用DelegatingActionProxy ,在Action 处完成转发。
****************采用DelegatingRequestProcessor *****************
在struts-config.xml文件中
去掉每个action中的type属性
增加
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
acton-servlet. xml 用于配置表现层context,其详细配置信息如下:
<?xml version="1.0" encoding="gb2312"?>
<!-- 指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-//SPR工NG//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd">
<!-- spring 配置文件的根元素一〉
<beans>
<!一每个request 请求产生新实例,所以将action 配置成non-singleton-->
<bean name="/login" class="lee.LoginAction" singleton="false">
<!一配置依赖注入-->
<property name="vb">
<!-- 引用容器中另外的bean-->
.......
</property>
</bean>
</beans>
由于每次请求时,都应该启动新的action 来处理用户请求,因此应将action bean 配
置成non-singleton行为。
注意: ActionServlet转发请求时,是根据bean 的name 属性,而不是id 属性。因此,
此处确定的name 属性应与Struts 的action 属性相同。
*******************采用DelegatingActionProxy **********************
与上面的方法相比,本方法只是稍作修改如下:
在struts-config.xml文件中
所有的action的type修改为:type="org.springframework.web.struts.DelegatingActionProxy"
去掉
<controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/>
就可以了
DelegatingActionProxy 接受ActionServlet 转发过来的请求,然后转发给
ApplicationContext管理的bean,这是典型的链式处理。
通过配置文件可看出,在struts-config.xml文件中配置了大量DelegatingActionProxy
实例, Spring 容器中也配置了同名的Action。即Struts 的业务控制器分成了两个部分:
第一个部分是Spring 的DelegatingActionProxy,这个部分没有实际意义,仅仅完成转发:
第二个部分是用户的Action 实现类,负责实际的处理工作。
这种策略的性能比前一种的策略要差一些,因为需要多创建一个DelegatingActionProxy
实例。而且在J2EE 应用中的Action 非常多,这将导致需要大量创建DelegatingActionProxy
实例,在使用一次之后,要等待垃圾回收机制回收,从而降低了其性能。
如果想struts不受spring容器的管理,而又要在action中使用spring容器中的bean的话
,我们可以在action中手动获得ApplicationContext 实例。在这种整合策略下, Struts 的Action 不接受IoC 容器管理,使Action 的代码与Spring API 部分耦合,这种策略也有其好处:代码的可读性非常强,在Action 的代码中显式调用业务逻辑组件时,无须等待容器注入。
在Action 中访问ApplicationContext 有以下两种方法:
·利用WebApplicationContextUtils 工具类。
·利用ActionSupport 支持类。
不过,这会造成很多冗余代码,在每个action中都要增加获取applicationContext的代码
有一种折中的办法就是实现一个BaseAction
//BaseAction 继承ActionSupport 类
public class BaseAction extends ActionSupport
{
public Object getBean(String beanName){
return getWebApplicationContext() .getBean(beanName);
}
}
然后每个action类都继承这个类,要使用spring容器中的bean时,直接使用
getBean()函数就可以了
很好地实现了控制层与业务逻辑层的分离