今天有一个朋友问了我一个问题,他使用的是Hibernate/Spring/Struts架构,配置使用Spring的 OpenSessionInView Filter,但是发现不生效,lazy的集合属性在页面访问的时候仍然报session已经关闭的错误。我和他一起检查了所有的配置和相关的代码,但是 没有发现任何问题。经过调试发现,应用程序使用的Session和OpenSessionInView Filter打开的Session不是同一个,所以OpenSessionInView模式没有生效,但是为什么他们不使用同一个Session呢?
检查了一遍Spring的相关源代码,发现了问题的根源:
通常在Web应用中初始化Spring的配置,我们会在web.xml里面配置一个Listener,即:
xml代码:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
如果使用Struts,那么需要在Struts的配置文件struts-config.xml里面配置一个Spring的plugin:ContextLoaderPlugIn。
实 际上ContextLoaderListener和ContextLoaderPlugIn的功能是重叠的,他们都是进行Spring配置的初始化工作 的。因此,如果你不打算使用OpenSessionInView,那么你并不需要在web.xml里面配置ContextLoaderListener。
好了,但是你现在既需要Struts集成Spring,又需要OpenSessionInView模式,问题就来了!
由于 ContextLoaderListener和ContextLoaderPlugIn功能重叠,都是初始化Spring,你不应该进行两次初始化,所以 你不应该同时使用这两者,只能选择一个,因为你现在需要集成Struts,所以你只能使用ContextLoaderPlugIn。
但是令人困惑的是,ContextLoaderListener和ContextLoaderPlugIn有一个非常矛盾的地方!
ContextLoaderListener初始化spring配置,然后把它放在ServletContext对象里面保存:
java代码:
servletContext.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
请注意,保存的对象的key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE!
但是ContextLoaderPlugIn初始化spring配置,然后把它放在ServletContext对象里面保存:
java代码:
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
这个attrName和WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE名字是不一样的!
如果仅仅是名字不一样,问题还不大,你仍然可以放心使用ContextLoaderPlugIn,但是当你使用OpenSessionInView的时候,OpenSessionInViewFilter是使用哪个key取得spring配置的呢?
java代码:
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配置。
——————————————————————————————————————————————————————
同时使用ContextLoaderListener和ContextLoaderPlugIn,但是不 要在ContextLoaderPlugIn里面加入applicationContext.xml,只要加入你的action- servlet.xml,我相信,同样也可以非常流畅的使用OpenSessionInView
整个配置如下:
1.首先是web.xml
java代码:
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
......
2. 然后是struts-config.xml:
java代码:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/action-servlet.xml"
/>
</plug-in>
http://hi.baidu.com/anypcao/blog/item/22a76a1e217c43fd1bd576b2.html
分享到:
相关推荐
### Spring + Hibernate OpenSessionInView 模式的理解和应用 在Java Web开发中,Spring与Hibernate作为两个重要的框架,经常被一起使用来实现业务逻辑与数据持久化的处理。而在使用这两个框架时,为了更好地管理...
为了练手培训,给大家准备的 Open...3.通过 open session in view filter 支持 延迟加载 4.在页面上通过 jstl 很优雅的获取数据 5.通过 spring aop(aspectJ) 声明事务 6.通过formular 映射参数表,指定两个死的变量
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <param-name>singleSession <param-value>true </filter> <filter-mapping> <filter-name>...
在Java Web开发中,OpenSessionInView(OSIV)模式是一种常见的解决数据持久化问题的设计模式,主要用于Spring框架与Hibernate等ORM工具的集成。这个模式的主要目的是解决在HTTP请求处理过程中,由于Session范围内的...
Spring框架是Java开发中不可或缺的一部分,它为开发者提供了丰富的功能,包括依赖注入、面向切面编程、事务管理等。在处理Web应用时,Spring提供了一些关键特性,如`CharacterEncodingFilter`和`...
同时,需要注意的是,OpenSessionInView模式虽然方便,但也会带来潜在的问题,如事务边界不清晰和会话泄漏。因此,在实际应用中,应结合具体需求谨慎使用,并考虑使用更现代的解决方案,如Spring Data JPA的...
在实际项目中,还需要在web.xml中配置DispatcherServlet、Struts2的Filter以及Spring的ContextLoaderListener。同时,需要编写相关的配置文件,如struts.xml、hibernate.cfg.xml、applicationContext.xml,以完成各...
4. **错误隐蔽**:由于延迟加载在视图渲染阶段才执行,一些本应在业务逻辑中发现的错误可能会被延迟暴露。 `数据库.txt` 和 `osiv` 这两个文件名可能是与数据库操作和OSIV模式相关的资料。`数据库.txt` 可能包含了...
<filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>...
<filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <!--...--> </filter> ``` 此过滤器保持一个打开的Hibernate ...
<filter-name>openSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class> <param-name>sessionFactoryBeanName <param-value>...
2. **OpenSessionInView模式**: 为了防止Session在请求结束后关闭导致数据丢失,我们可以使用`OpenSessionInViewFilter`。这个过滤器在每次请求开始时打开Session,结束时关闭,保证在整个视图渲染过程中Session都是...
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <param-name>encoding <param-value>UTF-8 </filter> <!-- Hibernate OpenSessionInView 过滤器 --> <filter> ...
这些JAR包通常包括但不限于: - Struts2核心库(例如struts2-core-x.x.x.jar)。 - Spring框架的核心库(例如spring-context-x.x.x.jar)。 - Hibernate的核心库(例如hibernate-core-x.x.x.jar)。 - 其他依赖...
然而,当我们在服务层关闭了Session后,到视图层进行数据填充时,可能会遇到已关闭的Session导致的数据不可用问题。OpenSessionInViewFilter就是为了缓解这一问题而设计的。 该过滤器的核心思想是在用户的HTTP请求...
<filter-name>OpenSessionInView</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>...
5. **OpenSessionInView模式** - 修改`HibernateSessionFactory.java`,实现线程局部变量存储事务对象。 - 实现`beginTransaction`、`commitTransaction`、`rollbackTransaction`等方法,确保在每次请求结束时关闭...
和Spring中OpenSessionInView由于org.springframework.web.struts.ContextLoaderPlugIn中保存同一个对象的名不同导致openSessionInView失效 稍微修改后在struts-config.xml中使用MyContextLoaderPlugIn.jar包中...
- `openSessionInView`模式是在Web层使用Filter打开和关闭Session,确保每个HTTP请求都有一个活跃的Session,以支持延迟加载。 6. Spring的事务管理: - 有两种方式:声明式事务(基于注解或XML配置)和编程式...
17. 单一不可变对象往往是线程安全的,但是复杂不可变对象需要保证其内部成员变量也是不可变的。 18. 良好的多线程编程习惯是:将所有的域都声明为final,除非它们是可变的。 19. 保证共享变量的发布是安全的,...