OpenSessionInViewFilter的一些原理

Spring中对OpenSessionInViewFilter的描述如下:

1.OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibernate的Session,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。

2.它是一个过滤器,用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。例如: 它允许在事务提交之后延迟加载显示所需要的对象。

public class OpenSessionInViewFilter extends OncePerRequestFilter {

public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

org.springframework.orm.hibernate3.support.OpenSessionInViewFilter继承了OncePerRequestFilter抽象类,

doFilter()方法是OpenSessionInViewFilter的父类OncePerRequestFilter(抽象类)的方法,是过滤器的入口,是处理请求的第一个方法,父类的doFilter()方法调用了doFilterInternal()方法

public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
    //首选判断进行过滤的是否是http请求
    if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
        throw new ServletException("OncePerRequestFilter just supports HTTP requests");
    }
    //如果是http请求的话进行强转
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    //alreadyFilteredAttributeName 是一个标识,用于判断是否需要进行OpenSessionInViewFilter
    String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
    if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(httpRequest)) {
        // Proceed without invoking this filter...
        filterChain.doFilter(request, response);
    }
    else {
        // Do invoke this filter...
        request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
        //下面这个方法是abstract方法由OpenSessionInViewFilter 实现,是OpenSessionInViewFilter 的核心方法
        doFilterInternal(httpRequest, httpResponse, filterChain);
    }
}

	protected abstract void doFilterInternal(
			HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException;

}

OpenSessionInViewFilter重写了doFilterInternal方法,

protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

//从spring的上下文中取得SessionFactory对象
SessionFactory sessionFactory = lookupSessionFactory(request);

//标识同一个请求的当前线程中存不存在Session,是不是共享同一个Session(SessionFactory里面对应的Session)
boolean participate = false;

//判断是否单session模式,当singleSession 设置为true是当页面跳转的时候是不是单例的,同一个Session。
if (isSingleSession()) {
//判断能否在当前线程中取得sessionFactory对象对应的session,一般只有Action跳Action的时候才会跑,其它时都是false
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
participate = true;
}else {
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");

//当前线程取不到session的时候通过sessionFactory创建,getSession()还在session中设置了flushMode,注意设置flushMode的模式。
Session session = getSession(sessionFactory);

/*将session绑定到当前的线程中,SessionHolder是session的一层封装,里面有个存放session的map,而且是线程同 步的Collections.synchronizedMap(newHashMap(1));*/
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
}else {
//这段是非单session模式的处理情况
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
// Do not modify deferred close: just set the participate flag.
participate = true;
}else {
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}

try {

//将session绑定到了当前线程后,就该处理请求了
filterChain.doFilter(request, response);
}


finally {
if (!participate) {
if (isSingleSession()) {
//当请求结束时,对于单session模式,这时候要取消session的绑定,因为web容器(Tomcat等)的线程是采用线程池机制的,线程使用过后并不会销毁.解除session的绑定就是从map里面移除

SessionHolder sessionHolder =(SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");

//取消绑定只是取消session对象和线程对象之间的引用,还没有关闭session,不关闭session相对于不关闭数据库连接,所以这里要关闭session
closeSession(sessionHolder.getSession(), sessionFactory);
}else {
SessionFactoryUtils.processDeferredClose(sessionFactory);
}
}
}
}

1.上面的源码中首先从lookupSessionFactory()方法中从Spring中获得一个SessionFactory,

	protected SessionFactory lookupSessionFactory() {
		if (logger.isDebugEnabled()) {
			logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
		}
		WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
		return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
	}

2. getSessionFactoryBeanName()方法默认返回"sessionFactory"字符串,在spring配置文件中可要注意了,如果是其它的名字,则要配正确。从这里看出Opensessioninview也需要sessionfactorybean的注入,他默认的去找beanidsessionfactorybean,如果sessionfactorybeanid不是这个名字的话,要记得给这个过滤器配置一个参数,参数名为sessionfactoryBeanName,把他的value设置为的sessionfactorybeanid值。

下一篇TransactionSynchronizationManager概述.还有SessionHolder类.

http://blog.sina.com.cn/s/blog_821025b70100w5b3.html

http://blog.163.com/juanming5612@126/blog/static/60345421201012115435606/

http://blog.csdn.net/sunyujia/article/details/2788192

http://www.iteye.com/topic/32001

http://blog.csdn.net/zxq1406spys/article/details/4748283




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值