`

spring的2种加载方式:ContextLoaderListener和ContextLoaderPlugIn

阅读更多
今天有一个朋友问了我一个问题,他使用的是Hibernate/Spring/Struts架构,配置使用Spring的OpenSessionInViewFilter,但是发现不生效,lazy的集合属性在页面访问的时候仍然报session已经关闭的错误。我和他一起检查了所有的配置和相关的代码,但是没有发现任何问题。经过调试发现,应用程序使用的Session和OpenSessionInView Filter打开的Session不是同一个,所以OpenSessionInView模式没有生效,但是为什么他们不使用同一个Session呢?

检查了一遍Spring的相关源代码,发现了问题的根源:

通常在Web应用中初始化Spring的配置,我们会在web.xml里面配置一个Listener,即:

<listener>  
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>  


如果使用Struts,那么需要在Struts的配置文件struts-config.xml里面配置一个Spring的plugin:ContextLoaderPlugIn。像这样:
 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
    <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml,/WEB-INF/action-servlet.xml" />
  </plug-in>


实际上ContextLoaderListener和ContextLoaderPlugIn的功能是重叠的,他们都是进行Spring配置的初始化工作的。因此,如果你不打算使用OpenSessionInView,那么你并不需要在web.xml里面配置ContextLoaderListener。

好了,但是你现在既需要Struts集成Spring,又需要OpenSessionInView模式,问题就来了!

由于ContextLoaderListener和ContextLoaderPlugIn功能重叠,都是初始化Spring,你不应该进行两次初始化,所以你不应该同时使用这两者,只能选择一个,因为你现在需要集成Struts,所以你只能使用ContextLoaderPlugIn。

但是令人困惑的是,ContextLoaderListener和ContextLoaderPlugIn有一个非常矛盾的地方!

ContextLoaderListener初始化spring配置,然后把它放在ServletContext对象里面保存:

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);


请注意,保存的对象的key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE!

但是ContextLoaderPlugIn初始化spring配置,然后把它放在ServletContext对象里面保存:

String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);


这个attrName和WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE名字是不一样的!

如果仅仅是名字不一样,问题还不大,你仍然可以放心使用ContextLoaderPlugIn,但是当你使用OpenSessionInView的时候,OpenSessionInViewFilter是使用哪个key取得spring配置的呢?
WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext(););


显然,OpenSessionInViewFilter是按照WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个key去拿spring配置的!

我们整理一下思路:

ContextLoaderPlugIn保存spring配置的名字叫做attrName;
ContextLoaderListener保存spring配置的名字叫做WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
而OpenSessionInView是按照WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE这个名字去取得spring配置的!
而你的应用程序却是按照attrName去取得spring的配置的!

所以,OpenSessionInView模式失效!

解决办法:
修改ContextLoaderPlugIn代码,在getServletContext().setAttribute(attrName, wac);这个地方加上一行代码:
getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);

或者修改OpenSessionInViewFilter,让它按照attrName去取得spring配置。
分享到:
评论
1 楼 juforg 2010-11-15  
有其它解决方案吗
改源码总觉得不好

相关推荐

    Spring整合Struts

    ContextLoaderPlugin是Spring为Struts设计的一个插件,它能够加载一个Spring配置文件,该文件指向由ContextLoaderListener加载的根WebApplicationContext作为其父上下文。默认情况下,配置文件的名称是映射的servlet...

    spring和struts整合的三种方案

    在实际应用中,第一种和第二种方案通常用于初始化 Spring 容器,而第三种方案则更深入地将 Spring 的功能集成到 Struts 请求处理流程中。然而,使用 `ActionSupport` 类(方法一)会使得 Struts Action 与 Spring ...

    使用MyEclipse集成SSH和DWR【最佳方案】

    - 相对于`ContextLoaderListener`来说,这种方式可能会稍微延迟Spring上下文的加载时间,但总体上也是一种可行的方案。 **示例配置:** ```xml &lt;!-- 通过ContextLoaderListener加载Spring配置文件 --&gt; ...

    ssh整合文档.txt

    - **解析**:通过`ContextLoaderPlugIn`插件,可以在启动Struts2时自动加载指定的Spring配置文件,从而实现Struts2与Spring的整合。 #### 三、web.xml配置详解 `web.xml`是Web应用的核心配置文件,用于配置监听器...

    Struts+Hibernate+Spring 最优配置

    3. **将Struts Action的管理委托给Spring框架**:通过在Struts配置文件中加入ContextLoaderPlugIn,可以将Spring的上下文加载到Struts环境中,从而实现Struts与Spring的深度集成。 ### 实施细节 为了实现上述的...

    struts+spring+hibernate全面整合

    Struts、Spring 和 Hibernate 是三个著名的 Java 开发框架,它们分别负责不同的职责:Struts 主要处理 MVC(Model-View-Controller)架构中的控制层,Spring 提供了强大的依赖注入和事务管理,而 Hibernate 则是 ORM...

    struts spring hibernate整合

    在`web.xml`中,我们需要定义一个Struts插件——`ContextLoaderPlugIn`,该插件负责加载Spring的配置文件。 ```xml &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt; ``` **2. 在...

    Struts Spring Hibernate 整合引用2008

    2. 直接在`web.xml`中加载Spring配置: 这种方式下,不再使用`&lt;plug-in&gt;`节点,而是通过`&lt;context-param&gt;`在`web.xml`中声明Spring的配置文件路径。同样需要配置`ContextLoaderListener`来初始化Spring容器。Action...

    spring与struts的整合

    - **ContextLoaderPlugIn**:该插件用于初始化Spring的应用上下文,将Spring配置文件加载到内存中。这里的`contextConfigLocation`属性指定了Spring配置文件的位置。 ##### 2. 配置ContextLoaderListener ```xml ...

    ssh三大框架整合

    如果不希望在`struts-config.xml`中配置`ContextLoaderPlugIn`插件,可以在`web.xml`中配置一个监听器`org.springframework.web.context.ContextLoaderListener`来装载Spring上下文。 2. **特点**: - 不使用...

    S2SH的配置文件

    - `plug-in`元素:配置Spring的`ContextLoaderPlugIn`插件,用于加载Spring配置文件`applicationContext.xml`。 ##### 3. Hibernate配置文件 - **位置**:Hibernate配置文件通常放置在`WEB-INF`目录下。 - **功能*...

    spring+struts+hibernate的配置文档

    - `ContextLoaderListener` 负责监听 Web 应用的启动和关闭事件,并在启动时加载指定的 Spring 配置文件。 - **字符集过滤器**:通过 `&lt;filter&gt;` 和 `&lt;filter-mapping&gt;` 元素配置了一个字符集过滤器 `...

    java 三个框架集成的 文档

    - **插件方式**:在`struts-config.xml`中添加`&lt;plug-in&gt;`元素,指定`ContextLoaderPlugIn`类,并设置`contextConfigLocation`属性指向Spring配置文件。 ```xml &lt;plug-in className="org.springframework.web....

    ssh配置,java三个框架联合开发

    ### SSH配置与Java三个框架联合开发详解 #### 一、SSH框架概述 SSH框架是指Spring、Struts2...通过这种方式,我们可以有效地利用Spring、Struts2和Hibernate这三个框架的优势,构建出高性能、高扩展性的Web应用系统。

    spring在web.xml中和在struts中的不同配置

    可以看出,有两种方法:一个是用 ContextLoaderListener 这个 Listerner,另一个是 ContextLoaderServlet 这个 Servlet,两者都是在 Web 应用启动的时候来初始化 WebApplicationContext。我个人认为 Listerner 要比 ...

    Myeclipse-ssh整合

    在`web.xml`中,指定Spring配置文件的位置并添加监听器`ContextLoaderListener`,加载配置文件`applicationContext.xml`。 ```xml &lt;!-- 指定配置文件位置 --&gt; &lt;param-name&gt;contextConfigLocation &lt;param-value&gt;...

Global site tag (gtag.js) - Google Analytics