OpenSessionInViewFilter
Session已关闭异常解决方法:
(1) 关闭延迟加载功能(不推荐使用)
(2) 使用Spring提供的OpenSessionInViewFilter类把Session关闭延长至页面加载数据完毕。

在web.xml中配置OpenSessionInViewFilter

Xml代码 复制代码 收藏代码
  1. <filter>

  2. <filter-name>

  3. OpenSessionInViewFilter

  4. </filter-name>

  5. <filter-class>

  6. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

  7. </filter-class>

  8. </filter>

  9. <filter-mapping>

  10. <filter-name>OpenSessionInViewFilter</filter-name>

  11. <url-pattern>*.do</url-pattern>

  12. </filter-mapping>

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

Xml代码 复制代码 收藏代码
  1. <listener>

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

  3. </listener>

  4. <context-param>

  5. <param-name>contextConfigLocation</param-name>

  6. <param-value>

  7. /WEB-INF/dao-config.xml,

  8. /WEB-INF/service-config.xml,

  9. /WEB-INF/spring-config.xml

  10. </param-value>

  11. </context-param>

如果使用Struts,那么需要在Struts的配置文件struts-config.xml里面配置一个Spring的plugin:ContextLoaderPlugIn。


注意:

要在应用中使用OpenSessionInViewFilter,加载Spring配置文件需要在web.xml中配置,如果是使用Spring提供的插件在struts-config.xml文件里进行配置,将出现获取不到ApplicationContext对象的异常。

原因是,OpenSessionInViewFilter类需要通过ApplicationContext获取sessionFactory对象时得不到ApplicationContext对象,

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

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

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

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

ContextLoaderListener和ContextLoaderPlugIn初始化spring配置后,都把配置对象放在ServletContext对象里面保存,问题在于他们各使用的key是不同的。而OpenSessionInViewFilter是按照ContextLoaderListener初始化后保存使用的key来获取配置对象,所以在使用ContextLoaderPlugIn初始化配置OpenSessionInViewFilter就得不到spring配置对象了。

这个问题解决办法是:
(1)修改OpenSessionInViewFilter代码,使之获取配置对象的key与ContextLoaderPlugIn初始化后用于保存的key一致。


(2) 使用ContextLoaderListener方式初始化配置。

--------------------------------------------------------------------------------------------------

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

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

Java代码 复制代码
  1. servletContext.setAttribute(

  2. WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.context);;



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

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

Java代码 复制代码
  1. String attrName =getServletContextAttributeName();;

  2. getServletContext();.setAttribute(attrName,wac);;



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

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

Java代码 复制代码
  1. WebApplicationContext wac =

  2. 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.重写struts的插件继承自spring的ContextLoaderPlugIn 的类。

  1. importorg.springframework.beans.BeansException;

  2. importorg.springframework.web.context.WebApplicationContext;

  3. importorg.springframework.web.context.support.WebApplicationContextUtils;

  4. importorg.springframework.web.struts.ContextLoaderPlugIn;

  5. publicclassMyContextLoaderPlugInextendsContextLoaderPlugIn{

  6. protectedWebApplicationContextinitWebApplicationContext()

  7. throwsBeansException,IllegalStateException {

  8. WebApplicationContext parent =WebApplicationContextUtils

  9. .getWebApplicationContext(getServletContext());

  10. WebApplicationContext wac =createWebApplicationContext(parent);

  11. String attrName =getServletContextAttributeName();

  12. getServletContext().setAttribute(attrName,wac);

  13. getServletContext().setAttribute(

  14. WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,

  15. wac);

  16. returnwac;

  17. }

  18. }

3.更改struts-config.xml

  1. <plug-in

  2. className="com.test.plugIn.MyContextLoaderPlugIn">

  3. <set-propertyproperty="contextConfigLocation"

  4. value="/WEB-INF/classes/spring/applicationContext.xml"/>

  5. </plug-in>