- 浏览: 11190 次
最新评论
为何不使用ContextLoaderPlugIn也可以正常使用DelegatingRequestProcessor和DelegatingActionProxy整
- 博客分类:
- Java编程
在整合Spring和Struts 1.x时候,网上面的教程都是教大家在struts配置里面增加一个叫org.springframework.web.struts.ContextLoaderPlugIn的插件,增加以下的配置:
struts-config.xml:
config.xml:
一般都是这样的方式的;这里ContextLoaderPlugin 的作用是通过contextConfigLocation配置的位置加载Spring的配置文件,生成WebApplicationContext对象,并将该对象放入ServletContext中,
对应的Key为:
因此在struts运行时候就已经生成了对应的Spring环境了。Action可以被注册成Spring Bean,纳入Spring管理。
但是有些时候,可以直接使用DelegatingRequestProcessor和DelegatingActionProxy而不需要使用ContextLoaderPlugIn来实现Action的Bean化。其实是因为我们已经使用了ContextLoaderListener/ContextLoaderServlet初始化了Spring的环境,使用时候我们只需要将Action的Bean加入到对应的Spring配置文件即可。
对于ContextLoaderPlugIn和ContextLoaderListener/ContextLoaderServlet的区别主要在于两种方式生成的WebApplicationContext,以不同的Key存放在ServletContext中,ContextLoaderPlugIn是以
而ContextLoaderListener/ContextLoaderServlet则是
既然两个Key不同,那么DelegatingRequestProcessor和DelegatingActionProxy能识别到吗!
DelegatingRequestProcessor是Spring提供的一个继承了struts的RequestProcessor类,使用时候直接在struts-config加入下面代码即可:
由于DelegatingRequestProcessor继承于RequestProcessor,RequestProcessor是struts的核心控制器,通过其来控制Action的创建以及调用,Spring就是在这里做了手脚,Spring重写了RequestProcessor的processActionCreate方法,修改了创建Action方式,通过action 配置中path作为Bean Name,通过Spring容器获取正真的Action对象,然后执行对应的响应方法。
DelegatingRequestProcessor:
DelegatingActionUtils:
WebApplicationContextUtils:
很明显在DelegatingRequestProcessor的init时候WebApplicationContext就已经通过DelegatingActionUtils.findRequiredWebApplicationContext方法获取到,而且很明显findRequiredWebApplicationContext是先根据
获取,如果没有就根据
获取,如果再没有获取到,就根据
获取,如果还是没有获取到就直接抛出异常。
DelegatingRequestProcessor是会在ServletContext查找ContextLoaderPlugIn和ContextLoaderListener/ContextLoaderServlet的Key,获取WebApplicationContext,然后通过WebApplicationContext获取对应的Action。因此DelegatingRequestProcessor是可以在没有ContextLoaderPlugIn的情况下正常运行的。
对于DelegatingActionProxy也是差不多的原理。
DelegatingActionProxy:
DelegatingActionProxy在execute时候也是通过DelegatingActionUtils.findRequiredWebApplicationContext获取WebApplicationContext,然后获取Action,来达到目的的。
附加:
配置使用Spring的OpenSessionInView Filter时候,因为OpenSessionInViewFilter是按照
这个key去拿spring配置的!
整理一下思路:
ContextLoaderPlugIn保存spring配置的key:
ContextLoaderListener保存spring配置的key
而OpenSessionInView是按照
这个名字去取得spring容器的!而你的应用程序却是按照ContextLoaderPlugIn的key去取得spring容器的。所以,OpenSessionInView模式失效!
如果使用了ContextLoaderPlugIn的Spring容器,而OpenSessionInViewFilter却获取了ContextLoaderListener的Spring容器。这样会导致Hibernate的session异常关闭的问题。如果配置了两个Spring容器,则刪除ContextLoaderPlugIn的加载方式。若只配置了ContextLoaderPlugIn的加载方式,则改成ContextLoaderListener加载方式。
struts-config.xml:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/config.xml" /> </plug-in>
config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="helloWorldService" class="com.strutstest.service.impl.HelloWorldServiceImpl"> </bean> <!--注意此处的映射必须与Struts中的动作对应 --> <bean name="/helloWorld" class="com.strutstest.action.HelloWorldAction"> <property name="helloWorldService"> <ref bean="helloWorldService" /> </property> </bean> </beans>
一般都是这样的方式的;这里ContextLoaderPlugin 的作用是通过contextConfigLocation配置的位置加载Spring的配置文件,生成WebApplicationContext对象,并将该对象放入ServletContext中,
对应的Key为:
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "配置文件前缀" //或者单纯的 ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX
因此在struts运行时候就已经生成了对应的Spring环境了。Action可以被注册成Spring Bean,纳入Spring管理。
但是有些时候,可以直接使用DelegatingRequestProcessor和DelegatingActionProxy而不需要使用ContextLoaderPlugIn来实现Action的Bean化。其实是因为我们已经使用了ContextLoaderListener/ContextLoaderServlet初始化了Spring的环境,使用时候我们只需要将Action的Bean加入到对应的Spring配置文件即可。
对于ContextLoaderPlugIn和ContextLoaderListener/ContextLoaderServlet的区别主要在于两种方式生成的WebApplicationContext,以不同的Key存放在ServletContext中,ContextLoaderPlugIn是以
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "配置文件前缀" //或者单纯的 ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX
而ContextLoaderListener/ContextLoaderServlet则是
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
既然两个Key不同,那么DelegatingRequestProcessor和DelegatingActionProxy能识别到吗!
DelegatingRequestProcessor是Spring提供的一个继承了struts的RequestProcessor类,使用时候直接在struts-config加入下面代码即可:
<!--告诉Struts用DelegatingRequestProcessor来代替原来的RequestProcessor --> <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor" />
由于DelegatingRequestProcessor继承于RequestProcessor,RequestProcessor是struts的核心控制器,通过其来控制Action的创建以及调用,Spring就是在这里做了手脚,Spring重写了RequestProcessor的processActionCreate方法,修改了创建Action方式,通过action 配置中path作为Bean Name,通过Spring容器获取正真的Action对象,然后执行对应的响应方法。
DelegatingRequestProcessor:
private WebApplicationContext webApplicationContext; public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException{ super.init(actionServlet, moduleConfig); if (actionServlet != null) { this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig); } } protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException { return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig); } protected final WebApplicationContext getWebApplicationContext() { return this.webApplicationContext; } protected Action processActionCreate(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException { Action action = getDelegateAction(mapping); if (action != null) { return action; } return super.processActionCreate(request, response, mapping); } protected Action getDelegateAction(ActionMapping mapping) throws BeansException { String beanName = determineActionBeanName(mapping); if (!getWebApplicationContext().containsBean(beanName)) { return null; } return (Action) getWebApplicationContext().getBean(beanName, Action.class); } protected String determineActionBeanName(ActionMapping mapping) { return DelegatingActionUtils.determineActionBeanName(mapping); }
DelegatingActionUtils:
public static WebApplicationContext findRequiredWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException { WebApplicationContext wac = getWebApplicationContext(actionServlet, moduleConfig); // If no Struts-specific context found, fall back to root context. if (wac == null) { wac = WebApplicationContextUtils.getRequiredWebApplicationContext(actionServlet.getServletContext()); } return wac; } public static String determineActionBeanName(ActionMapping mapping) { String prefix = mapping.getModuleConfig().getPrefix(); String path = mapping.getPath(); String beanName = prefix + path; if (logger.isDebugEnabled()) { logger.debug("DelegatingActionProxy with mapping path '" + path + "' and module prefix '" + prefix + "' delegating to Spring bean with name [" + beanName + "]"); } return beanName; } public static WebApplicationContext getWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig) { WebApplicationContext wac = null; String modulePrefix = null; // Try module-specific attribute. if (moduleConfig != null) { modulePrefix = moduleConfig.getPrefix(); wac = (WebApplicationContext) actionServlet.getServletContext().getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + modulePrefix); } // If not found, try attribute for default module. if (wac == null && !"".equals(modulePrefix)) { wac = (WebApplicationContext) actionServlet.getServletContext().getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX); } return wac; }
WebApplicationContextUtils:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { Assert.notNull(sc, "ServletContext must not be null"); Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); if (attr == null) { return null; } if (attr instanceof RuntimeException) { throw (RuntimeException) attr; } if (attr instanceof Error) { throw (Error) attr; } if (!(attr instanceof WebApplicationContext)) { throw new IllegalStateException("Root context attribute is not of type WebApplicationContext: " + attr); } return (WebApplicationContext) attr; } public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException { WebApplicationContext wac = getWebApplicationContext(sc); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?"); } return wac; }
很明显在DelegatingRequestProcessor的init时候WebApplicationContext就已经通过DelegatingActionUtils.findRequiredWebApplicationContext方法获取到,而且很明显findRequiredWebApplicationContext是先根据
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "配置文件前缀"
获取,如果没有就根据
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX
获取,如果再没有获取到,就根据
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
获取,如果还是没有获取到就直接抛出异常。
DelegatingRequestProcessor是会在ServletContext查找ContextLoaderPlugIn和ContextLoaderListener/ContextLoaderServlet的Key,获取WebApplicationContext,然后通过WebApplicationContext获取对应的Action。因此DelegatingRequestProcessor是可以在没有ContextLoaderPlugIn的情况下正常运行的。
对于DelegatingActionProxy也是差不多的原理。
DelegatingActionProxy:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Action delegateAction = getDelegateAction(mapping); return delegateAction.execute(mapping, form, request, response); } protected Action getDelegateAction(ActionMapping mapping) throws BeansException { WebApplicationContext wac = getWebApplicationContext(getServlet(), mapping.getModuleConfig()); String beanName = determineActionBeanName(mapping); return (Action) wac.getBean(beanName, Action.class); } protected WebApplicationContext getWebApplicationContext(ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException { return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig); } protected String determineActionBeanName(ActionMapping mapping) { return DelegatingActionUtils.determineActionBeanName(mapping); }
DelegatingActionProxy在execute时候也是通过DelegatingActionUtils.findRequiredWebApplicationContext获取WebApplicationContext,然后获取Action,来达到目的的。
附加:
配置使用Spring的OpenSessionInView Filter时候,因为OpenSessionInViewFilter是按照
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
这个key去拿spring配置的!
整理一下思路:
ContextLoaderPlugIn保存spring配置的key:
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "配置文件前缀" //或者单纯的 ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX
ContextLoaderListener保存spring配置的key
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
而OpenSessionInView是按照
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
这个名字去取得spring容器的!而你的应用程序却是按照ContextLoaderPlugIn的key去取得spring容器的。所以,OpenSessionInView模式失效!
如果使用了ContextLoaderPlugIn的Spring容器,而OpenSessionInViewFilter却获取了ContextLoaderListener的Spring容器。这样会导致Hibernate的session异常关闭的问题。如果配置了两个Spring容器,则刪除ContextLoaderPlugIn的加载方式。若只配置了ContextLoaderPlugIn的加载方式,则改成ContextLoaderListener加载方式。
- 部分源代码.zip (8.8 KB)
- 下载次数: 0
相关推荐
通过这种方式,可以实现Action与业务逻辑的解耦,并利用Spring的依赖注入特性,使得Action能够更加灵活地被配置和使用。 1. **使用DelegatingRequestProcessor** - **原理**:`DelegatingRequestProcessor`类是...
1. 覆盖Struts的默认RequestProcessor,使用Spring的DelegatingRequestProcessor。 2. 在的type属性中使用DelegatingActionProxy类。 这两种方法都能让你在action-context.xml文件中管理Action及其依赖关系。通过在...
- 在`struts-config.xml`中,Action配置改为`DelegatingActionProxy`类型,这样Struts会委托给Spring来创建和管理Action实例。 - 在Spring的`applicationContext.xml`中,定义Action Bean并指定其映射路径。 通过...
整合Spring和Struts可以提升应用的可维护性和灵活性,同时也允许开发人员充分利用Spring的强大功能,如事务管理、数据访问抽象、AOP等。然而,随着技术的发展,现在许多项目已经转向使用Spring Boot或Spring MVC,...
这样,Action 类可以访问 Spring 容器,但同时也意味着 Action 类与 Spring 有较高的耦合度,且 Action 并不在 Spring 的管理范围内,无法处理一个 Action 类中包含多个动作的情况。 步骤如下: - 添加 Spring 和 ...
这种方式主要是通过使用Spring提供的`DelegatingRequestProcessor`类来替代Struts默认的`RequestProcessor`,从而实现Spring和Struts的解耦。 ##### 实施步骤 1. **配置Controller和ContextLoaderPlugIn** 在`...
如果不想修改Action中的`type`属性,还可以通过使用`DelegatingRequestProcessor`来实现Spring与Struts的集成。在Struts的配置文件中,添加一个`ContextLoaderPlugIn`插件,并设置`contextConfigLocation`属性,指向...
- 第二种方法是使用`DelegatingActionProxy`,不配置controller节点,而是改变Action的type属性为`DelegatingActionProxy`,然后在Spring配置文件中进行依赖注入。 - 第三种方法是Action直接获取Spring的IOC容器...
根据提供的文件信息,可以看出这里涉及的是Spring框架与SSH(Struts、Spring、Hibernate)集成的相关配置及使用场景。下面将详细解析这些知识点。 ### Spring框架与SSH集成 #### Spring框架介绍 Spring框架是一个...
与第二种方法类似,也需要配置`DelegatingActionProxy`作为Action的类型。 这种方式的优点在于它提供了更多的灵活性,可以更细致地控制请求处理流程。 #### 四、手动创建ApplicationContext进行整合 **1. web.xml...
将 Action 的类型更改为 `org.springframework.web.struts.DelegatingActionProxy`,这使得 Struts 可以通过 Spring 来管理和实例化 Action 类。 5. **Spring 注入 Action**: 在 Spring 的配置文件中,定义 ...
2. **使用 `DelegatingActionProxy`**:不需在 `struts-config.xml` 中配置 `controller`,而是直接更改 Action 节点的 `type` 属性为 `DelegatingActionProxy`。同样,要在 Spring 配置文件中设置 Action Bean 及其...
12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器...
org.springframework.web.struts.DelegatingActionProxy.class org.springframework.web.struts.DelegatingActionUtils.class org.springframework.web.struts.DelegatingRequestProcessor.class org.spring...
### Struts+Spring+...此外,使用Spring的依赖注入特性可以更好地管理组件间的依赖关系,而Hibernate则为数据持久化提供了强大的支持。整体而言,这种组合是当前Java企业级应用开发中非常流行且高效的解决方案之一。
DelegatingRequestProcessor DelegatingServletInputStream DelegatingServletOutputStream DelegatingThemeSource DelegatingTilesRequestProcessor DelegatingTimerListener DelegatingTimerTask ...