今天有一个朋友问了我一个问题,他使用的是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配置。
分享到:
相关推荐
ContextLoaderPlugin是Spring为Struts设计的一个插件,它能够加载一个Spring配置文件,该文件指向由ContextLoaderListener加载的根WebApplicationContext作为其父上下文。默认情况下,配置文件的名称是映射的servlet...
在实际应用中,第一种和第二种方案通常用于初始化 Spring 容器,而第三种方案则更深入地将 Spring 的功能集成到 Struts 请求处理流程中。然而,使用 `ActionSupport` 类(方法一)会使得 Struts Action 与 Spring ...
- 相对于`ContextLoaderListener`来说,这种方式可能会稍微延迟Spring上下文的加载时间,但总体上也是一种可行的方案。 **示例配置:** ```xml <!-- 通过ContextLoaderListener加载Spring配置文件 --> ...
- **解析**:通过`ContextLoaderPlugIn`插件,可以在启动Struts2时自动加载指定的Spring配置文件,从而实现Struts2与Spring的整合。 #### 三、web.xml配置详解 `web.xml`是Web应用的核心配置文件,用于配置监听器...
3. **将Struts Action的管理委托给Spring框架**:通过在Struts配置文件中加入ContextLoaderPlugIn,可以将Spring的上下文加载到Struts环境中,从而实现Struts与Spring的深度集成。 ### 实施细节 为了实现上述的...
Struts、Spring 和 Hibernate 是三个著名的 Java 开发框架,它们分别负责不同的职责:Struts 主要处理 MVC(Model-View-Controller)架构中的控制层,Spring 提供了强大的依赖注入和事务管理,而 Hibernate 则是 ORM...
在`web.xml`中,我们需要定义一个Struts插件——`ContextLoaderPlugIn`,该插件负责加载Spring的配置文件。 ```xml <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> ``` **2. 在...
2. 直接在`web.xml`中加载Spring配置: 这种方式下,不再使用`<plug-in>`节点,而是通过`<context-param>`在`web.xml`中声明Spring的配置文件路径。同样需要配置`ContextLoaderListener`来初始化Spring容器。Action...
- **ContextLoaderPlugIn**:该插件用于初始化Spring的应用上下文,将Spring配置文件加载到内存中。这里的`contextConfigLocation`属性指定了Spring配置文件的位置。 ##### 2. 配置ContextLoaderListener ```xml ...
如果不希望在`struts-config.xml`中配置`ContextLoaderPlugIn`插件,可以在`web.xml`中配置一个监听器`org.springframework.web.context.ContextLoaderListener`来装载Spring上下文。 2. **特点**: - 不使用...
- `plug-in`元素:配置Spring的`ContextLoaderPlugIn`插件,用于加载Spring配置文件`applicationContext.xml`。 ##### 3. Hibernate配置文件 - **位置**:Hibernate配置文件通常放置在`WEB-INF`目录下。 - **功能*...
- `ContextLoaderListener` 负责监听 Web 应用的启动和关闭事件,并在启动时加载指定的 Spring 配置文件。 - **字符集过滤器**:通过 `<filter>` 和 `<filter-mapping>` 元素配置了一个字符集过滤器 `...
- **插件方式**:在`struts-config.xml`中添加`<plug-in>`元素,指定`ContextLoaderPlugIn`类,并设置`contextConfigLocation`属性指向Spring配置文件。 ```xml <plug-in className="org.springframework.web....
### SSH配置与Java三个框架联合开发详解 #### 一、SSH框架概述 SSH框架是指Spring、Struts2...通过这种方式,我们可以有效地利用Spring、Struts2和Hibernate这三个框架的优势,构建出高性能、高扩展性的Web应用系统。
可以看出,有两种方法:一个是用 ContextLoaderListener 这个 Listerner,另一个是 ContextLoaderServlet 这个 Servlet,两者都是在 Web 应用启动的时候来初始化 WebApplicationContext。我个人认为 Listerner 要比 ...
在`web.xml`中,指定Spring配置文件的位置并添加监听器`ContextLoaderListener`,加载配置文件`applicationContext.xml`。 ```xml <!-- 指定配置文件位置 --> <param-name>contextConfigLocation <param-value>...