- 浏览: 7339438 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (1546)
- 企业中间件 (236)
- 企业应用面临的问题 (236)
- 小布Oracle学习笔记汇总 (36)
- Spring 开发应用 (54)
- IBatis开发应用 (16)
- Oracle基础学习 (23)
- struts2.0 (41)
- JVM&ClassLoader&GC (16)
- JQuery的开发应用 (17)
- WebService的开发应用 (21)
- Java&Socket (44)
- 开源组件的应用 (254)
- 常用Javascript的开发应用 (28)
- J2EE开发技术指南 (163)
- EJB3开发应用 (11)
- GIS&Mobile&MAP (36)
- SWT-GEF-RCP (52)
- 算法&数据结构 (6)
- Apache开源组件研究 (62)
- Hibernate 学习应用 (57)
- java并发编程 (59)
- MySQL&Mongodb&MS/SQL (15)
- Oracle数据库实验室 (55)
- 搜索引擎的开发应用 (34)
- 软件工程师笔试经典 (14)
- 其他杂项 (10)
- AndroidPn& MQTT&C2DM&推技术 (29)
- ActiveMQ学习和研究 (38)
- Google技术应用开发和API分析 (11)
- flex的学习总结 (59)
- 项目中一点总结 (20)
- java疑惑 java面向对象编程 (28)
- Android 开发学习 (133)
- linux和UNIX的总结 (37)
- Titanium学习总结 (20)
- JQueryMobile学习总结 (34)
- Phonegap学习总结 (32)
- HTML5学习总结 (41)
- JeeCMS研究和理解分析 (9)
最新评论
-
lgh1992314:
[u][i][b][flash=200,200][url][i ...
看看mybatis 源代码 -
尼古拉斯.fwp:
图片根本就不出来好吧。。。。。。
Android文件图片上传的详细讲解(一)HTTP multipart/form-data 上传报文格式实现手机端上传 -
ln94223:
第一个应该用排它网关吧 怎么是并行网关, 并行网关是所有exe ...
工作流Activiti的学习总结(八)Activiti自动执行的应用 -
ZY199266:
获取不到任何消息信息,请问这是什么原因呢?
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息 -
xiaoyao霄:
DestinationSourceMonitor 报错 应该导 ...
ActiveMQ 通过JMX监控Connection,Queue,Topic的信息
最近不知道干些什么好,无论做什么都觉得没劲,为了强迫自己学习,准备研究些开源项目的源码,从中找点乐趣,先来个大家熟悉的OpenSessionInViewFilter,下面我将逐步分析OpenSessionInViewFilter 的源码,了解OpenSessionInViewFilter 的原理,欣赏spring优雅的代码,本文只分析源码不做功能介绍,如果有朋友不熟悉OpenSessionInViewFilter,但是又有兴致阅读此文可以先百度或google一下.
Spring中对OpenSessionInViewFilter的描述如下:
它是一个Servlet2.3过滤器,用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。例如: 它允许在事务提交之后延迟加载显示所需要的对象。
下面从处理请求的入口读起,下面所指的session均为hibernate session不再特别说明,本文观点纯属个人观点如有错误请批评指正不胜感激.
OpenSessionInViewFilter 的父类OncePerRequestFilter(抽象类)的方法,是过滤器的入口,是处理请求的第一个方法.
- 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);
- }
- }
好下面让我们进入doFilterInternal一探究竟
- protected void doFilterInternal(HttpServletRequest request,
- HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
- /**
- * 从spring的上下文中取得SessionFactory对象
- * WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
- * return (SessionFactory) wac.getBean(getSessionFactoryBeanName(),SessionFactory.class);
- * getSessionFactoryBeanName()方法默认返回"sessionFactory"字符串,在spring配置文件中可要注意了,别写错了.
- */
- SessionFactory sessionFactory = lookupSessionFactory(request);
- boolean participate = false;// 标识过滤器结束时是否进行关闭session等后续处理
- if (isSingleSession()) {//单session模式
- //判断能否在当前线程中取得sessionFactory对象对应的session
- if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
- //当能够找到session的时候证明会有相关类处理session的收尾工作,这个过滤器不能进行关闭session操作,否则会出现重复关闭的情况.
- participate = true;//但我并没有想出正常使用的情况下什么时候会出现这种情况.
- } else {
- Session session = getSession(sessionFactory);//当前线程取不到session的时候通过sessionFactory创建,下面还会详细介绍此方法
- //将session绑定到当前的线程中,SessionHolder是session的一层封装,里面有个存放session的map,而且是线程同步的Collections.synchronizedMap(new HashMap(1));
- //但是单session模式下一个SessionHolder对应一个session,核心方法是getValidatedSession 取得一个open状态下的session,并且取出后从map中移出.
- TransactionSynchronizationManager.bindResource(sessionFactory,
; new SessionHolder(session));
下面详细介绍TransactionSynchronizationManager的几个关键的方法
- public abstract class TransactionSynchronizationManager {
- //线程局部变量,为每一个使用该变量的线程都提供一个变量值的副本,每一个线程都可以独立地改变自己的副本,而不会与其它线程的副本冲突,用于存放session
- private static final ThreadLocal resources = new ThreadLocal();
- public static boolean hasResource(Object key) {//判断当前线程是否已经绑定了session,key是sessionFactory对象,一个sessionFactory可以绑定一个session
- Assert.notNull(key, "Key must not be null");//spring的Assert类不错,大家可以看看很简单
- Map map = (Map) resources.get();
- return (map != null && map.containsKey(key));
- }
- public static void bindResource(Object key, Object value) throws IllegalStateException {//绑定session到当前线程
- Assert.notNull(key, "Key must not be null");
- Assert.notNull(value, "Value must not be null");
- Map map = (Map) resources.get();//ThreadLocal对象只可以存放一个对象,所以使用map来扩展
- if (map == null) {
- map = new HashMap();
- resources.set(map);
- }
- if (map.containsKey(key)) {
- throw new IllegalStateException("Already value [" + map.get(key) + "] for key [" + key +
- "] bound to thread [" + Thread.currentThread().getName() + "]");
- }
- map.put(key, value);
- }
- static Object unbindResource(Object key) throws IllegalStateException {//取消当前线程对session的绑定
- Assert.notNull(key, "Key must not be null");
- Map map = (Map) resources.get();
- if (map == null || !map.containsKey(key)) {
- throw new IllegalStateException(
- "No value for key [" + key + "] bound to thread [" + Thread.currentThread().getName() + "]");
- }
- Object value = map.remove(key);
- if (map.isEmpty()) {
- resources.set(null);
- }
- return value;
- }
- 另外一个非常关键的方法是OpenSessionInViewFilter的getSession方法,我们看这个方法的关键并不是如何取得session,而且注意这里设置了FlushMode
- protected Session getSession(SessionFactory sessionFactory)
- throws DataAccessResourceFailureException {
- Session session = SessionFactoryUtils.getSession(sessionFactory, true);
- FlushMode flushMode = getFlushMode();//默认情况下是FlushMode.NEVER
- if (flushMode != null) {
- session.setFlushMode(flushMode);
- }
- return session;
-
}
读到这个地方,大家对ThreadLocal 感兴趣的话,可以看下我以前写的一篇文章http://blog.csdn.net/sunyujia/archive/2008/06/15/2549564.aspx
FlushMode.NEVER:
调用Session的查询方法时,不清理缓存
调用Session.commit()时,不清理缓存
调用Session.flush()时,清理缓存
不过FlushMode.NEVER已经不再建议使用了
官方描述如下
Deprecated. use MANUAL instead. 使用FlushMode.MANUAL来代替
The Session is never flushed unless Session.flush() is explicitly called by the application. This mode is very efficient for read only transactions.
直到调用Session.flush()才会将变化反应到数据库,在只读的情况下是效率非常高的
详见http://www.hibernate.org/hib_docs/v3/api/org/hibernate/FlushMode.html
我们来细看SessionFactoryUtils.getSession(sessionFactory, true);- public static Session getSession(SessionFactory sessionFactory, boolean allowCreate) throws DataAccessResourceFailureException, IllegalStateException {
- try {
- return doGetSession(sessionFactory, null, null, allowCreate);
- }
- catch (HibernateException ex) {
- throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
- }
- }
从上面可以看出doGetSession才是真正的核心方法,这里非常重要的是HibernateTemplate也是调用此方法
- protected Session getSession() {
- if (isAlwaysUseNewSession()) {
- return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());
- }else if (!isAllowCreate()) {
- return SessionFactoryUtils.getSession(getSessionFactory(), false);
- }else {
- return SessionFactoryUtils.getSession(
- getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
- }
- }
无论如何调用最后都是落实到SessionFactoryUtils.doGetSession这个方法上面,无论这个方法最后是否返回了null实际上在方法中都取得了session,
这是整个流程中最复杂的一个方法,部分代码我理解的也很不好,大家一起研究研究.- private static Session doGetSession(
- SessionFactory sessionFactory, Interceptor entityInterceptor,
- SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
- throws HibernateException, IllegalStateException {
- Assert.notNull(sessionFactory, "No SessionFactory specified");
- //取当前线程绑定
- 的session
- SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
- //sessionHolder就可以看成是当前线程绑定的session了
- if (sessionHolder != null && !sessionHolder.isEmpty()) {
- Session session = null;
- if (TransactionSynchronizationManager.isSynchronizationActive() &
- sessionHolder.doesNotHoldNonDefaultSession()) {//判断spring的事务管理是否是激活的,同时SessionHolder对象中有且仅有一个session
- // Spring transaction management is active ->
- // register pre-bound Session with it for transactional flushing.
- session = sessionHolder.getValidatedSession();
- //在开事务的时候HibernateTransactionManager类中的doBegin方法会将isSynchronizedWithTransaction设置为true,暂时不知道什么情况下会进入如下代码块
- if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
- TransactionSynchronizationManager.registerSynchronization(
- new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
- sessionHolder.setSynchronizedWithTransaction(true);
- // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
- // with FlushMode.NEVER, which needs to allow flushing within the transaction.
- FlushMode flushMode = session.getFlushMode();
- if (flushMode.lessThan(FlushMode.COMMIT) &
- !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
- session.setFlushMode(FlushMode.AUTO);
- sessionHolder.setPreviousFlushMode(flushMode);
- }
- }
- }
- else {
- // No Spring transaction management active -> try JTA transaction synchronization.
- //在没用事务的情况下下面的方法中只调用了sessionHolder.getValidatedSession();
- session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
- }
- if (session != null) {
- return session;//在使用了OpenSessionInViewFilter的情况下,HibernateTemplate执行此方法会在这里return
- }
- }
- //如果当前线程没有绑定session那么无论如何都是要创建session的,但是否会return还要取决于allowCreate等条件,在后面会看到
- Session session = (entityInterceptor != null ?
- sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());
- // Use same Session for further Hibernate actions within the transaction.
- // Thread object will get removed by synchronization at transaction completion.
- //判断spring的事务管理是否是激活的,目前我分析结果是在单session情况下,只有OpenSessionInViewFilter调用此方法,才会执行到这里,这种情况下是不会有事务的.
- //可见下面if块里面的代码是针对非单session,并且有事务的情况处理的.
- if (TransactionSynchronizationManager.isSynchronizationActive())& ;{
- // We're within a Spring-managed transaction, possibly from JtaTransactionManager.
- logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
- SessionHolder holderToUse = sessionHolder;
- if (holderToUse == null) {
- holderToUse = new SessionHolder(session);
- }
- else {
- holderToUse.addSession(session);
- }
- if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
- session.setFlushMode(FlushMode.NEVER);//只读情况下,可以提高效率同时也防止了脏数据等
- }
- TransactionSynchronizationManager.registerSynchronization(
- new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
- holderToUse.setSynchronizedWithTransaction(true);//这个变量真是很费解不知道什么情况下会为false呢?
- if (holderToUse != sessionHolder) {//从这里可以看出非单session情况下,有事务也是要绑定session的只是颗粒度不同而已,我猜非单session事务结束后session就被关闭了.
- TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
- }
- }
- else {
- // No Spring transaction management active -> try JTA transaction synchronization.
- registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
- }
- // Check whether we are allowed to return the Session.
- //校验能否创建session的动作居然是放在创建session之后处理的,有点不解.
- if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
- closeSession(session);
- throw new IllegalStateException("No Hibernate Session bound to thread, " +
- "and configuration does not allow creation of non-transactional one here");
- }
- return session;
- }
发表评论
-
【转】在项目中使用多个数据源-多sessionFactory方案
2013-05-10 16:30 3131适用范围:适合SSH架构访问多个数据库, ... -
【转】使用spring的动态路由实现数据库负载均衡
2013-03-17 22:57 3307使用spring的动态路由实现数据库负载均衡 系统中 ... -
【转】spring 数据库读写分离
2013-03-17 22:56 2804什么是数据库的读写分离 数据库的读写分离简单的说是把对数据 ... -
[转]Spring+iBatis+JOTM实现JTA事务
2013-03-17 22:51 3059Spring+iBatis+JOTM实现JTA事务 ... -
Spring 和Axis2整合相关那些事
2012-12-29 12:58 10421Axis2优劣: 现在用axis2开发一个webse ... -
【转】JAVA并发容器代码随读
2012-12-06 15:29 2954转载自 http://rdc.taobao.c ... -
Spring3.04和Junit4
2011-11-27 18:15 4396在Spring3.x以上必须采用 ... -
Spring加载属性文件的扩展
2011-08-22 12:21 3026在项目中一个属性文件配置信息,提供给数据连接信息 ... -
Brap和Spring整合(简单权限验证)
2011-07-26 10:31 1390在使用Spring的发 ... -
Quartz的任务的临时启动和暂停和恢复
2011-07-16 10:18 40226在项目中需要手动启停某些服务,那么需要有一个控 ... -
Quartz中定时调度EJB3.0服务
2011-07-13 22:25 2937在quartz2.0中只支持EJb2.0的服务 ... -
Quartz中定时调度EJB2.0服务
2011-07-13 22:12 2181在Quartz2.0中提供支持EJB2.0 ... -
Quartz的简单使用
2011-07-13 22:05 9956最近工作需要学习quartz,那么必须首先了解三个概念:调度器 ... -
Brap 远程访问调用 和Spring整合(二)
2010-12-08 14:52 2006Brap和 Spring 整合使用如 ... -
闲着没事Hessian开发WebService的总结(二)
2010-12-07 20:30 4034在Spring和Hessian整合中,以前 ... -
Spring JMX的学习总结(三) 基于注释的JMX的使用
2010-12-03 17:26 3362具体实现JMX的注释的类: package c ... -
Spring JMX的总结学习(二) 注解实现MBean
2010-12-03 17:24 6282本文采用Spring JMX ... -
Spring JMX的总结学习(一)基于标准接口的JMX
2010-12-03 17:21 3780在Spring中采用JMX标准形式的,开发相关的Spr ... -
Spring JMS的开发应用--自定义消息转换器的使用(四)
2010-12-03 01:37 2511在Spring JMS、中可以通过实现Me ... -
Spring JBOSSMQ JMS的开发应用(三)
2010-11-30 20:11 2345如果用过JMS的话,会发现它类似写JD ...
相关推荐
通过阅读《OpenSessionInViewFilter说明.doc》文档,你可以更深入地了解其内部实现细节、配置方法以及如何在实际项目中合理使用。这个文档应该包含了OpenSessionInViewFilter的源码分析、配置示例以及常见问题的解答...
OpenSessionInViewFilter个人学习总结
SSH是Java Web开发中的一个流行框架组合,由Struts、Hibernate和Spring三个组件构成。这个框架集成提供了模型-视图-控制器(MVC)架构,数据持久化,以及依赖注入和事务管理等功能,大大简化了企业级应用的开发工作...
Struts2、Spring和Hibernate是Java开发中三个非常重要的框架,它们共同构成了经典的MVC(Model-View-Controller)架构的实现。这个压缩包“struts2.0.8+spring2.0+hibernate3.2”包含了这三个框架的特定版本,这将...
- 在高并发场景下,需要注意OpenSessionInViewFilter可能会导致的性能问题,因为它使得Session的生命周期变长,增加了Session占用资源的时间。 - 如果项目中同时使用了其他Session管理机制,需要确保它们之间不会...
在探讨如何通过`OpenSessionInViewFilter`来有效管理Hibernate中的Session生命周期之前,我们需要先理解Session及其生命周期的基本概念。 #### Session与生命周期 在Hibernate框架中,`Session`是执行数据库操作的...
首先,让我们深入了解一下`CharacterEncodingFilter`。在Web应用中,字符编码问题常常引发乱码问题,尤其是在用户输入的数据与服务器处理数据之间存在编码不一致时。`CharacterEncodingFilter`的作用就是确保请求和...
该模式的核心在于通过Spring提供的`OpenSessionInViewFilter`过滤器,在视图渲染过程中保持Hibernate Session的打开状态,从而简化了事务管理,并避免了一些常见的懒加载异常。 #### 一、OpenSessionInViewFilter...
OpenSessionInViewFilter解决Web应用程序的问题
**S2SH集成详解** ...总的来说,这个S2SH集成案例涵盖了Web应用开发的关键技术,从用户交互到数据持久化,再到事务管理,为初学者提供了一个完整的实践平台,有助于深入理解和掌握Java Web开发的核心概念。
为了解决这个问题,我们可以使用 Spring 提供的一个支持类OpenSessionInViewFilter,这个类可以在发起一个页面请求时打开 Hibernate 的 Session,并保持这个 Session 的生命周期,直到这个请求结束。这样可以确保 ...
### Spring监听器与过滤器详解...- **Spring Web环境下的监听器和过滤器**:在Spring MVC环境中,除了上述提到的OpenSessionInViewFilter和CharacterEncodingFilter,还有多种其他类型的过滤器和监听器可以使用,例如`...
Struts2、Spring和Hibernate是Java开发中的三大框架,它们的集成...开发者需要对这三个框架有深入理解,才能顺利完成这样的集成工作。同时,对于新版本的Hibernate,开发者需要了解其变化,以便进行适应性的代码调整。
本次讨论将围绕给定的`web.xml`和`struts.xml`配置文件进行深入解析,并结合这些配置文件中的具体内容来阐述相关的知识点。 ## 二、`web.xml`配置分析 ### 2.1 Spring配置 在`web.xml`文件中,首先定义了Spring的...
因此,以下将围绕这部分内容进行深入解析,详细介绍如何在Web项目中整合这三大框架。 ### Struts2、Spring、Hibernate集成 #### 1. 创建Web Project项目 首先,在开发环境中创建一个新的Web项目。这通常在IDE(如...
2. **OpenSessionInViewFilter**:通过Web容器的过滤器(filter)来实现。 #### 异常原因 当使用Open Session In View模式时,如果Session的Flush Mode被设置为NEVER,并且尝试执行写操作(如更新或删除),就会触发...
在`web.xml`中配置Spring监听器以初始化Spring容器,并添加`OpenSessionInViewFilter`以解决懒加载问题: ```xml <listener-class>org.springframework.web.context.ContextLoaderListener <filter-name>...
本文将深入解析SSH框架整合的配置文件,旨在为开发者提供全面的理解与指导。 ### SSH框架整合的核心:配置文件 #### 1. **web.xml** —— Servlet容器的配置文件 `web.xml`是Web应用程序的核心配置文件,用于配置...
### Spring学习笔记知识点详解 #### 一、面向接口(抽象)编程的概念与好处 面向接口编程是一种编程方式,强调在设计系统时...通过深入理解这些知识点,可以帮助开发者更好地掌握 Spring 框架的核心原理和技术实践。
在 OpenSessionInViewFilter 中,需要配置 Hibernate 的 Session 管理,以便实现 Hibernate 的 Session 的打开和关闭。 9. web.xml 配置 在 web.xml 文件中,需要配置 Servlet 监听器、上下文变量、Filter 等,...