j2ee

假设我们使用的是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()函数就可以了

很好地实现了控制层与业务逻辑层的分离
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值