---恢复内容开始---

 /*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.orm.hibernate4.support; import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.OncePerRequestFilter; /**
* Servlet 2.3 Filter that binds a Hibernate Session to the thread for the entire
* processing of the request. Intended for the "Open Session in View" pattern,
* i.e. to allow for lazy loading in web views despite the original transactions
* already being completed.
*使用过滤器将请求的全部 hibernate session 绑定到线程。 用于“打开回话视图” 模式,
    允许在web 视图中延迟加载,尽管基本的事务已经完成,(虽然事务已经提交完成,但任然允许延迟加载数据?)
* <p>This filter makes Hibernate Sessions available via the current thread, which
* will be autodetected by transaction managers. It is suitable for service layer
* transactions via {@link org.springframework.orm.hibernate4.HibernateTransactionManager}
* as well as for non-transactional execution (if configured appropriately).
*这个过滤器使hibernaete session 可以通过当前线程,其将自动检测事务管理,适合于服务处通过HibernateTransactionManager 管理事务,以及非事务执行(如果适当配置)
    
* <p><b>NOTE</b>: This filter will by default <i>not</i> flush the Hibernate Session,
* with the flush mode set to {@code FlushMode.NEVER}. It assumes to be used
* in combination with service layer transactions that care for the flushing: The
* active transaction manager will temporarily change the flush mode to
* {@code FlushMode.AUTO} during a read-write transaction, with the flush
* mode reset to {@code FlushMode.NEVER} at the end of each transaction.
*
* <p><b>WARNING:</b> Applying this filter to existing logic can cause issues that
* have not appeared before, through the use of a single Hibernate Session for the
* processing of an entire request. In particular, the reassociation of persistent
* objects with a Hibernate Session has to occur at the very beginning of request
* processing, to avoid clashes with already loaded instances of the same objects.
*
* <p>Looks up the SessionFactory in Spring's root web application context.
* Supports a "sessionFactoryBeanName" filter init-param in {@code web.xml};
* the default bean name is "sessionFactory".
*
* @author Juergen Hoeller
* @since 3.1
* @see #lookupSessionFactory
* @see OpenSessionInViewInterceptor
* @see OpenSessionInterceptor
* @see org.springframework.orm.hibernate4.HibernateTransactionManager
* @see org.springframework.transaction.support.TransactionSynchronizationManager
* @see org.hibernate.SessionFactory#getCurrentSession()
*/
public class OpenSessionInViewFilter extends OncePerRequestFilter { public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory"; private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME; /**
* Set the bean name of the SessionFactory to fetch from Spring's
* root application context. Default is "sessionFactory".
* @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
*/
public void setSessionFactoryBeanName(String sessionFactoryBeanName) {
this.sessionFactoryBeanName = sessionFactoryBeanName;
} /**
* Return the bean name of the SessionFactory to fetch from Spring's
* root application context.
*/
protected String getSessionFactoryBeanName() {
return this.sessionFactoryBeanName;
} /**
* Returns "false" so that the filter may re-bind the opened Hibernate
* {@code Session} to each asynchronously dispatched thread and postpone
* closing it until the very last asynchronous dispatch.
      返回false 是因为这个filter 可以开启session的异步只读操作模式,延迟关闭它直到异步加载完成。
*/
@Override
protected boolean shouldNotFilterAsyncDispatch() {
return false;
} /**
* Returns "false" so that the filter may provide a Hibernate
* {@code Session} to each error dispatches.
       返回false以便这个filter可以提供一个session的错误输出。
*/
@Override
protected boolean shouldNotFilterErrorDispatch() {
return false;
} @Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
     //通过指定的名称获取sessionFactory 
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;
    //通过当前的request请求获得web 异步管理器,如果没有异步管理器则创建一个并与request关联。
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        
        //返回一个请求的属性名称已用于识别其已经过滤。
String key = getAlreadyFilteredAttributeName();
      //检测这个sessionFactory是否绑定到当前线程。
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
participate = true;
}
else {
          //这个过滤器是否是异步执行的,因为一个filter是可以调用多个线程的单个请求的。
boolean isFirstRequest = !isAsyncDispatch(request);
if (isFirstRequest || !applySessionBindingInterceptor(asyncManager, key)) {
logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
Session session = openSession(sessionFactory);
            //包装一个session以使下一句将其绑定到thread.
SessionHolder sessionHolder = new SessionHolder(session);
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
         //实例化一个opensessionInViewFilter类专用的异步请求拦截器,从其类解释来看很有必要。
AsyncRequestInterceptor interceptor = new AsyncRequestInterceptor(sessionFactory, sessionHolder);
            //将异步请求拦截器与reques关联
asyncManager.registerCallableInterceptor(key, interceptor);
            //延迟的请求
asyncManager.registerDeferredResultInterceptor(key, interceptor);
}
} try {
filterChain.doFilter(request, response);
} finally {
if (!participate) {
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
if (!isAsyncStarted(request)) {
logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
}
} /**
* Look up the SessionFactory that this filter should use,
* taking the current HTTP request as argument.
* <p>The default implementation delegates to the {@link #lookupSessionFactory()}
* variant without arguments.
* @param request the current request
* @return the SessionFactory to use
*/
protected SessionFactory lookupSessionFactory(HttpServletRequest request) {
return lookupSessionFactory();
} /**
* Look up the SessionFactory that this filter should use.
* <p>The default implementation looks for a bean with the specified name
* in Spring's root application context.
* @return the SessionFactory to use
* @see #getSessionFactoryBeanName
*/
protected SessionFactory lookupSessionFactory() {
if (logger.isDebugEnabled()) {
logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
}
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
} /**
* Open a Session for the SessionFactory that this filter uses.
* <p>The default implementation delegates to the {@link SessionFactory#openSession}
* method and sets the {@link Session}'s flush mode to "MANUAL".
       打开session因为filter要使用,同时将session的事务提交模式设置为手动提交(MANUAL)
* @param sessionFactory the SessionFactory that this filter uses
* @return the Session to use
* @throws DataAccessResourceFailureException if the Session could not be created
* @see org.hibernate.FlushMode#MANUAL
*/
protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
try {
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
return session;
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
}
}
  
      
     /*检测前面获取的请求属性名是否已注册至异步管理器中,如果已经注册了,则通过绑定到当前线程的sessionFactory创建session*/ 
private boolean applySessionBindingInterceptor(WebAsyncManager asyncManager, String key) {
if (asyncManager.getCallableInterceptor(key) == null) {
return false;
}
        
((AsyncRequestInterceptor) asyncManager.getCallableInterceptor(key)).bindSession();
return true;
} }

---恢复内容结束---

org.springframework.orm.hibernate4.support.OpenSessionInViewFilter的更多相关文章

  1. ssh中org.springframework.orm.hibernate4.support.OpenSessionInViewFilter的作用及配置

     org.springframework.orm.hibernate4.support.OpenSessionInViewFilter 是Spring为我们解决Hibernate的Session的关闭 ...

  2. org.springframework.orm.hibernate4.support.OpenSessionInterceptor

    /* * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Vers ...

  3. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter作用

    在Spring与Hibernate集成时在web.xml要加入这样的过滤器: <filter> <filter-name>openSessionInView</filte ...

  4. Caused by: java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.HibernateTemplate

    1.错误描述 严重: Context initialization failed org.springframework.beans.factory.CannotLoadBeanClassExcept ...

  5. hibernate4 , spring3 使用 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean 报错 Implementing class

    错误代码如下 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with ...

  6. org.springframework.orm.hibernate3.HibernateSystemException:

    org.springframework.orm.hibernate3.HibernateSystemException: The database returned no natively gener ...

  7. java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.LocalSessionFactoryBean

    Caused by: java.lang.ClassNotFoundException: org.springframework.orm.hibernate3.LocalSessionFactoryB ...

  8. Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider停住了

    2015.1.24进行了服务器的搬家,搬家后,更换了新的IP,导致新的IP访问以前IP的数据库服务无法成功Initializing connection provider: org.springfra ...

  9. org.springframework.orm.hibernate3.LocalSessionFactoryBean的疑惑解决办法

    在项目中使用了SSH框架(Struts2 + Spring3+ Hibernate3),applicationContext中配置了sessionFactory <bean id="s ...

随机推荐

  1. keywords和favicon

    1.<meta name="keywords" content="xxx"> 曾经网站风靡关键词堆积,往往在首页上设置大量的关键词,以获取最大范围搜 ...

  2. HDU1087 Super Jumping! Jumping! Jumping! —— DP

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1087 Super Jumping! Jumping! Jumping! Time Limi ...

  3. [NOI 2012] 美食节

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2879 [算法] 首先 , 将每种食物建一个点 , 将每位厨师做的每一道菜建一个点 建 ...

  4. ['1' for i in range(4)]

    ' for i in range(4)]) 结果: [']

  5. java笔记之IO2写操作

    IO流的分类 流向: 输入流  读出数据 输出流 写出数据 数据类型 字节流 字节输入流 读取数据 inputstream 字节输出流 写出数据 outputstream 字符流 字符输入流 读取数据 ...

  6. asp.net mvc razer

    Asp.net MVC Razor模板引擎技巧分享 http://www.cnblogs.com/JustRun1983/p/3545303.html 全新的membership框架Asp.net I ...

  7. asp.net MVC4 学习(一)

    asp.net MVC 回顾 Html.ActionLink http://www.cnblogs.com/jiagoushi/p/3905828.html 选择基本模板,视图引擎 选择Razor A ...

  8. bzoj 2288: 【POJ Challenge】生日礼物【链表+堆】

    参考:http://blog.csdn.net/w_yqts/article/details/76037315 把相同符号的连续数字加起来,合并后ans先贪心的加上所有正数,如果正数个数sum> ...

  9. P1971 [NOI2011]兔兔与蛋蛋游戏

    传送门 思路比较迷--题解在这里 //minamoto #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R ...

  10. 「vijos」lxhgww的奇思妙想(长链剖分)

    传送门 长链剖分的板子(又是乱搞优化暴力) 对于每一个点,我们定义它深度最深的子节点为它的重儿子(为什么不叫长儿子……),他们之间的连边为重边 然后长链剖分有几个性质 1.总链长为$O(n)$ 2.一 ...