08-Spring提供OpenSessionInViewFilter过滤器和Struts2过滤器之间的配置顺序
Spring 所提供的过滤器和监听器
Introspector 缓存清除监听器
Spring 还提供了一个名为 org.springframework.web.util.IntrospectorCleanupListener 的监听器。它主要负责处理由 JavaBean Introspector 功能而引起的缓存泄露。IntrospectorCleanupListener 监听器在 Web 应用关闭的时会负责清除 JavaBean Introspector 的缓存,在 web.xml 中注册这个监听器可以保证在 Web 应用关闭的时候释放与其相关的 ClassLoader 的缓存和类引用。如果您使用了 JavaBean Introspector 分析应用中的类,Introspector 缓存会保留这些类的引用,结果在应用关闭的时候,这些类以及Web 应用相关的 ClassLoader 不能被垃圾回收。不幸的是,清除 Introspector 的唯一方式是刷新整个缓存,这是因为没法准确判断哪些是属于本 Web 应用的引用对象,哪些是属于其它 Web 应用的引用对象。所以删除被缓存的 Introspection 会导致将整个 JVM 所有应用的 Introspection 都删掉。需要注意的是,Spring 托管的 Bean 不需要使用这个监听器,因为 Spring 的 Introspection 所使用的缓存在分析完一个类之后会马上从 javaBean Introspector 缓存中清除掉,并将缓存保存在应用程序特定的 ClassLoader 中,所以它们一般不会导致内存资源泄露。但是一些类库和框架往往会产生这个问题。例如 Struts 和 Quartz 的 Introspector 的内存泄漏会导致整个的 Web 应用的 ClassLoader 不能进行垃圾回收。在 Web 应用关闭之后,您还会看到此应用的所有静态类引用,这个错误当然不是由这个类自身引起的。解决这个问题的方法很简单,您仅需在 web.xml 中配置 IntrospectorCleanupListener 监听器就可以了:
JAVA工程师简历模板
2、在web.xml中配置OpenSessionInViewFilter。
2011/06 -- 2011/11
计算机与信息工程学院信息管理系统
软件环境:MySQL、Tomcat 6.0、Ibatis、Struts、Spring、JSP、Ajax、CSS、DIV等
经验总结:
通过本系统的开发,首次体验了服务器的搭建,网站开发过程中前台与后台的融合,学会了数据库的增删改查操作,以及感受到团队开发的高效。
教育经历
2009/09 --2013/06
XXXXXXXX|计算机科学与技术|本科
在校学习情况
曾获院校级一等奖学金
2012/06国家级创新设计“三等奖”|国家级
2012/11全国大学生“挑战杯”大赛“三等奖”|国家级
项目描述:
该系统主要面向公司内部,完成公司人事管理、员工签到管理以及人员信息登记业务。人事管理业务包括长期工(有固定职位、职称的工作人员)与短期实习工(无职位)等。员工签到管理包括上下班打卡记录以及考勤记录等信息。只有管理员能够查询与修改所有人员上班记录;增、删、查、改员工信息、管理员信息;按日生成员工签到记录;按月生成月人员签到信息统计报表并允许员工通过Internet查询自己当前和以往上下班签到记录。
项目总结:
在查询数据时经常会出现Hibernate延迟加载问题,由于我们控制事务是在BIZ层,但是有些Entity用到了延迟加载,当需要在显示层显示的时候Hibernate才会把延迟的代理通Session去数据库中获取数据,但是这时候事务已经关闭了意味着session也结束了生命周期,这样就会造成LazyInitializationException,此类异常的解决:
SpringBoot中filter的使用详解及原理
SpringBoot中filter的使用详解及原理Spring Boot是基于Spring Framework的快速开发框架,它通过自动配置,简化了Spring的配置过程。
在Spring Boot中使用filter,可以方便地实现对请求和响应的过滤和处理。
本文将详细介绍Spring Boot 中filter的使用方法和原理。
一、使用filter的步骤1. 创建一个实现javax.servlet.Filter接口的类,实现其doFilter方法。
2. 在该类上使用javax.servlet.annotation.WebFilter注解标明该类是一个filter,并指定其拦截的URL模式。
二、filter的原理在Spring Boot中,使用filter的原理是通过Servlet容器来实现的。
当一个请求到达Servlet容器时,Servlet容器会根据配置的过滤器链依次将请求转发给各个filter进行处理,最终再将请求传递给目标Servlet或者Controller处理。
处理完请求后,再按照相反的顺序将响应返回给客户端。
三、filter的执行顺序在Spring Boot中,filter的执行顺序是根据filter的声明顺序决定的。
在WebMvcConfigurer中,可以通过addFilter方法将filter添加到过滤器链中,并且可以根据需要设置filter的顺序。
如果没有配置filter的顺序,默认按照filter类的名称的字母顺序执行。
四、示例代码下面我们以一个简单的登录认证的filter为例,来演示filter的使用方法和原理。
1. 创建LoginFilter类,实现javax.servlet.Filter接口,并重写doFilter方法。
```public class LoginFilter implements Filterpublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException//进行登录认证的逻辑,例如检查是否存在登录凭证等//...//如果认证通过,继续执行后续的过滤器链}``````public class Application extends WebMvcConfigurerAdapterpublic static void main(String[] args)}public void addFilters(FilterRegistrationBean registrationBean)registrationBean.setFilter(new LoginFilter();registrationBean.addUrlPatterns("/api/*");registrationBean.setOrder(1); // 设置filter的顺序}```经过上述配置后,每当有请求以"/api/"开头时,该请求会先经过LoginFilter的doFilter方法进行处理,然后再继续执行后续的过滤器链。
延迟加载lazy与OpenSessionInView
它有两种配置方式OpenSessionInViewInterceptor和OpenSessionInViewFilter(具体参看SpringSide),功能相同,只是一个在web.xml配置,另一个在application.xml配置而已。
OpenSessionInView在request把session绑定到当前thread期间一直保持hibernate session在open状态,使session在request的整个期间都可以使用,如在View层里PO也可以lazy loading数据,如 ${ company.employees }。当View 层逻辑完成后,才会通过Filter的doFilter方法或Interceptor的postHandle方法自动关闭session。
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
FlushMode.AUTO or remove 'readOnly' marker from transaction definition
看看OpenSessionInViewFilter里的几个方法
protected void doFilterInternal(HttpServletRequest request,
代码
<set name="groupses" table="usergroups" catalog="many" cascade="save-update" lazy="true">
SSH中session的关闭
Session的关闭方法第一种方法:主要都系用到Spring 提供openSessionInview思想.两个方法,都是Sping框架提供。
1.SPRING过滤器<filter-name> openSessionInviewFilter</filter-name><filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filterclas s></filter><filter-mapping><filter-name>openSessionInviewFilter</filter-name><url-pattern>/* </url-pattern></filter-mapping>2.Spring AOP 思想:<bean id="openSessionInViewInterceptor"class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"><property name="sessionFactory" ref="sessionFactory"/></bean><bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMa pping"><property name="interceptors" ref="openSessionInViewInterceptor"/><property name="mappings"><props>......</props></property></bean>第二种方法:既然你用到ssh,我就直接说一种最好方法了在web.xml中加入个filterXML code。
SpringBoot使用过滤器拦截器分析
SpringBoot使用过滤器拦截器分析过滤器和拦截器是用来拦截和处理请求的组件,它们在请求被处理之前或之后对请求进行一系列的操作和处理。
在 Spring Boot 中,我们可以使用过滤器和拦截器来实现一些通用的功能,比如认证、授权、日志记录等。
过滤器和拦截器的区别在于它们的位置和使用场景。
过滤器是基于Servlet 规范实现的,它位于请求和目标资源之间,可以对 requests 和responses 进行处理。
拦截器是 Spring 框架自己的一种组件,它可以在请求进入 Spring MVC 控制器之前或之后进行处理。
在 Spring Boot 中使用过滤器和拦截器非常简单,下面我们将分别对它们进行详细分析。
过滤器使用过滤器的第一步是创建一个过滤器类,并实现 doFilter( 方法,这个方法中可以编写过滤器的逻辑处理代码。
在 doFilter( 方法中,我们可以通过 request 和 response 对象来获取和修改请求和响应的属性和数据。
拦截器拦截器是 Spring 框架自己的一种组件,它可以在请求进入控制器之前或之后进行处理。
拦截器需要实现org.springframework.web.servlet.HandlerInterceptor 接口。
拦截器还可以通过实现 HandlerInterceptorAdapter 类来简化拦截器的实现。
应用场景分析过滤器和拦截器可以用于很多场景,下面我们将对一些常见的应用场景进行分析。
1.认证和授权过滤器和拦截器可以用于认证和授权的场景。
使用过滤器或拦截器可以在请求进入控制器之前进行用户认证,比如检查用户是否登录、用户是否有权限访问该资源等。
2.日志记录过滤器和拦截器可以用于记录请求的日志信息。
比如在请求进入控制器之前,可以记录请求的URL、请求的参数、请求的方法等信息;在请求完成之后,可以记录请求的响应码、响应的内容等信息。
3.参数验证过滤器和拦截器可以用于参数验证的场景。
3、OpenSessionInViewFilter说明
OpenSessionInViewFilter详解OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开Hibernate的Session,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。
由于Hibernate引入了Lazy Load特性,使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoad的Exception。
所以为了解决这个问题,Spring引入了这个Filter,使得Hibernate的Session的生命周期变长。
首先分析一下它的源码,可以发现,它所实现的功能其实比较简单:代码1.SessionFactory sessionFactory =lookupSessionFactory(request);2.Session session = null;3.boolean participate = false;4.5.if (isSingleSession()) {6.// single session mode7.if(TransactionSynchronizationManager.hasResource(sessionFactory)) {8.// Do not modify the Session: just set the participateflag.9. participate = true;10. } else {11. logger.debug("Opening single Hibernate Session inOpenSessionInViewFilter");12. session = getSession(sessionFactory);13. TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));14. }15.} else {16. // deferred close mode17. if(SessionFactoryUtils.isDeferredCloseActive(sessionFactory)){18.// Do not modify deferred close: just set the participateflag.19. participate = true;20. } else {21. SessionFactoryUtils.initDeferredClose(sessionFactory);22. }23.}24.25.try {26. filterChain.doFilter(request, response);27.} finally {28. if (!participate) {29. if (isSingleSession()) {30. // single session mode31. TransactionSynchronizationManager.unbindResource(sessionFactory);32. logger.debug("Closing single HibernateSession in OpenSessionInViewFilter");33. closeSession(session, sessionFactory);34. }else {35. // deferred close mode36. SessionFactoryUtils.processDeferredClose(sessionFactory);37. }38.}39.}在上述代码中,首先获得SessionFactory,然后通过SessionFactory获得一个Session。
SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系⼀简介(1)过滤器:依赖于servlet容器。
在实现上基于函数回调,可以对⼏乎所有请求进⾏过滤,但是缺点是⼀个过滤器实例只能在容器初始化时调⽤⼀次。
使⽤过滤器的⽬的是⽤来做⼀些过滤操作,获取我们想要获取的数据,⽐如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest 的⼀些参数,包括:过滤低俗⽂字、危险字符等关于过滤器的⼀些⽤法可以参考我写过的这些:(2)拦截器:依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。
在实现上基于的反射机制,属于⾯向切⾯(AOP)的⼀种运⽤。
由于拦截器是基于web框架的调⽤,因此可以使⽤Spring的依赖注⼊(DI)进⾏⼀些业务操作,同时⼀个拦截器实例在⼀个controller⽣命周期之内可以多次调⽤。
但是缺点是只能对controller请求进⾏拦截,对其他的⼀些⽐如直接访问静态资源的请求则没办法进⾏拦截处理关于过滤器的⼀些⽤法可以参考我写过的这些⽂章:⼆多个过滤器与拦截器的代码执⾏顺序如果在⼀个中仅仅只有⼀个拦截器或者过滤器,那么我相信相对来说理解起来是⽐较容易的。
但是我们是否思考过:如果⼀个项⽬中有多个拦截器或者过滤器,那么它们的执⾏顺序应该是什么样的?或者再复杂点,⼀个项⽬中既有多个拦截器,⼜有多个过滤器,这时它们的执⾏顺序⼜是什么样的呢?下⾯我将⽤简单的代码来测试说明:(1)先定义两个过滤器:i)过滤器1:package cn.zifangsky.filter;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.filter.OncePerRequestFilter;public class TestFilter1 extends OncePerRequestFilter {protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {//在DispatcherServlet之前执⾏system.out.println("############TestFilter1 doFilterInternal executed############");filterChain.doFilter(request, response);//在视图页⾯返回给客户端之前执⾏,但是执⾏顺序在Interceptor之后System.out.println("############TestFilter1 doFilter after############");// try {// Thread.sleep(10000);// } catch (InterruptedException e) {// e.printStackTrace();// }}}ii)过滤器2:package cn.zifangsky.filter;import java.io.IOException;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.filter.OncePerRequestFilter;public class TestFilter2 extends OncePerRequestFilter {protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {System.out.println("############TestFilter2 doFilterInternal executed############");filterChain.doFilter(request, response);System.out.println("############TestFilter2 doFilter after############");}}iii)在web.xml中注册这两个过滤器:<!-- ⾃定义过滤器:testFilter1 --><filter><filter-name>testFilter1</filter-name><filter-class>cn.zifangsky.filter.TestFilter1</filter-class></filter><filter-mapping><filter-name>testFilter1</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- ⾃定义过滤器:testFilter2 --><filter><filter-name>testFilter2</filter-name><filter-class>cn.zifangsky.filter.TestFilter2</filter-class></filter><filter-mapping><filter-name>testFilter2</filter-name><url-pattern>/*</url-pattern></filter-mapping>2)再定义两个拦截器:i)拦截器1,基本拦截器:package cn.zifangsky.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class BaseInterceptor implements HandlerInterceptor{/*** 在DispatcherServlet之前执⾏* */public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("************BaseInterceptor preHandle executed**********");return true;}/*** 在controller执⾏之后的DispatcherServlet之后执⾏* */public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {System.out.println("************BaseInterceptor postHandle executed**********");}/*** 在页⾯渲染完成返回给客户端之前执⾏* */public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {System.out.println("************BaseInterceptor afterCompletion executed**********");// Thread.sleep(10000);}}ii)指定controller请求的拦截器:package cn.zifangsky.interceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;public class TestInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("************TestInterceptor preHandle executed**********");return true;}public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {System.out.println("************TestInterceptor postHandle executed**********");}public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {System.out.println("************TestInterceptor afterCompletion executed**********");}}iii)在SpringMVC的中注册这两个拦截器:<!-- 拦截器 --><mvc:interceptors><!-- 对所有请求都拦截,公共拦截器可以有多个 --><bean name="baseInterceptor" class="cn.zifangsky.interceptor.BaseInterceptor"/><!-- <bean name="testInterceptor" class="cn.zifangsky.interceptor.TestInterceptor" /> --><mvc:interceptor><!-- 对/test.html进⾏拦截 --><mvc:mapping path="/test.html"/><!-- 特定请求的拦截器只能有⼀个 --><bean class="cn.zifangsky.interceptor.TestInterceptor"/></mvc:interceptor></mvc:interceptors>(3)定义⼀个测试使⽤的controller:package cn.zifangsky.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class TestController {@RequestMapping("/test.html")public ModelAndView handleRequest(){System.out.println("---------TestController executed--------");return new ModelAndView("test");}}4)视图页⾯test.jsp:<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><base href="/7311475/"><title>FilterDemo</title></head><body><%System.out.println("test.jsp is loading");%><div align="center">This is test page</div></body></html>5)测试效果:启动此测试项⽬,可以看到控制台中输出如下:这就说明了过滤器的运⾏是依赖于servlet容器的,跟springmvc等框架并没有关系。
Spring拦截器和过滤器的区别在哪?
Spring拦截器和过滤器的区别在哪?⽬录⼀、概述⼆、拦截器和过滤器介绍2.1 过滤器 (Filter)2.2 拦截器 (Interceptor)2.3 主要区别三、拦截器和过滤器的区别3.1 实现原理不同3.2 使⽤范围不同3.3 触发时机不同3.4 拦截的请求范围不同3.5 注⼊Bean情况不同3.6 控制执⾏顺序不同四、本⽂⼩结⼀、概述拦截器和过滤器filter和拦截器的功能都是拦截,filter拦截的⽬标是servlet的执⾏,⽽拦截器拦截的是Spring MVC定义的概念,叫handler(常见的就是我们⽤RequestMapping定义出来的HandlerMethod)。
觉得它相似是因为Spring的handler就是DispatcherServlet使⽤的,⽽后者就是⼀个servlet。
filter包围着dispatcherServlet,⽽它⾃⼰也想去执⾏⼀个⽬标handler,并在执⾏周围包裹着拦截器,好处是拦截器可以被容器管理,从⽽获得被容器赋予的能⼒,⽽filter不⾏(这样⼀想和代理filter使⽤applicationFilterChain很类似,只是拦截器更贴近执⾏业务的⽅法)。
没有什么其它更本质上的区别。
⼆、拦截器和过滤器介绍我们在项⽬中同时配置拦截器和过滤器。
2.1 过滤器 (Filter)过滤器的配置⽐较简单,直接实现Filter 接⼝即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接⼝中定义了三个⽅法。
init() :该⽅法在容器启动初始化过滤器时被调⽤,它在 Filter 的整个⽣命周期只会被调⽤⼀次。
「注意」:这个⽅法必须执⾏成功,否则过滤器会不起作⽤。
doFilter() :容器中的每⼀次请求都会调⽤该⽅法, FilterChain ⽤来调⽤下⼀个过滤器 Filter。
destroy():当容器销毁过滤器实例时调⽤该⽅法,⼀般在⽅法中销毁或关闭资源,在过滤器 Filter 的整个⽣命周期也只会被调⽤⼀次。
Filter(过滤器)简介和工作原理
2022-10-27 12:40Filter(过滤器)简介Filter 的基本功能是对Servlet 容器调用Servlet 的过程进行拦截,从而在Servlet 进行响应处理的先后实现一些特殊的功能。
在Servlet API 中定义了三个接口类来开供开辟人员编写Filter 程序:Filter, FilterChain, FilterConfigFilter 程序是一个实现了Filter 接口的Java 类,与Servlet 程序相似,它由Servlet 容器进行调用和执行Filter 程序需要在web.xml 文件中进行注册和设置它所能拦截的资源:Filter 程序可以拦截Jsp, Servlet, 静态图片文件和静态Filter 的基本工作原理当在web.xml 中注册了一个Filter 来对某个Servlet 程序进行拦截处理时,这个Filter 就成为了Servlet 容器与该Servlet 程序vlet 容器发送给Servlet 程序的请求和Servlet 程序回送给Servlet 容器的相应进行拦截,可以决定是否将请求继续传递给Se在一个web 应用程序中可以注册多个Filter 程序,每一个Filter 程序都可以对一个或者一组Servlet 程序进行拦截。
若有多个Filter 程序对某个Servlet 程序的访问过程进行拦截,当针对该Servlet 的访问请求到达时,web 容器将把这多个F 链中各个Filter 的拦截顺序与它们在应用程序的web.xml 中映射的顺序一致Filter 接口init(FilterConfig filterConfig)throws ServletException:在web 应用程序启动时,web 服务器将根据web.xml 文件中的配置信存在服务器的内存中。
Web 容器创建Filter 对象实例后,将即将调用该Filter 对象的init 方法。
OpenSessionInView的失效问题
OpenSessionInView的失效问题今天有一个朋友问了我一个问题,他使用的是Hibernate/Spring/Struts架构,配置使用Spring的OpenSessionInView Filter,但是发现不生效,lazy的集合属性在页面访问的时候仍然报session已经关闭的错误。
我和他一起检查了所有的配置和相关的代码,但是没有发现任何问题。
经过调试发现,应用程序使用的Session和OpenSessionInView Filter打开的Session不是同一个,所以OpenSessionInView模式没有生效,但是为什么他们不使用同一个Session呢?检查了一遍Spring的相关源代码,发现了问题的根源:通常在Web应用中初始化Spring的配置,我们会在web.xml里面配置一个Listener,即:Xml代码1.<listener>2.<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>3.</listener>如果使用Struts,那么需要在Struts的配置文件struts-config.xml里面配置一个Spring的plugin:ContextLoaderPlugIn。
实际上ContextLoaderListener和ContextLoaderPlugIn的功能是重叠的,他们都是进行Spring配置的初始化工作的。
因此,如果你不打算使用OpenSessionInView,那么你并不需要在web.xml里面配置ContextLoaderListener。
好了,但是你现在既需要Struts集成Spring,又需要OpenSessionInView模式,问题就来了!由于ContextLoaderListener和ContextLoaderPlugIn功能重叠,都是初始化Spring,你不应该进行两次初始化,所以你不应该同时使用这两者,只能选择一个,因为你现在需要集成Struts,所以你只能使用ContextLoaderPlugIn。
Spring源码解析--SpringWeb过滤器Filter解析
Spring源码解析--SpringWeb过滤器Filter解析Spring 源码解析 -- SpringWeb过滤器Filter解析简介在上⼏篇⽂章中探索了请求处理相关的代码,本篇开始探索请求处理前的⼀些操作代码,如Filter。
本篇探索Filter初始化、请求处理等相关代码。
前⾔说先简单的定义相关的测试代码:启动类:import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;@ServletComponentScan@SpringBootApplicationpublic class SpringExampleApplication {public static void main(String[] args) {SpringApplication.run(SpringExampleApplication.class, args);}}Controller相关代码:import er;import org.springframework.web.bind.annotation.*;@RestControllerpublic class HelloWorld {@GetMapping("/")public String helloWorld(@RequestParam(value = "id") Integer id,@RequestParam(value = "name") String name) {return "Hello world:" + id;}@GetMapping("/test1")public String helloWorld1(@RequestParam(value = "id") Integer id) {return "Hello world:" + id;}@PostMapping("/test2")public String helloWorld2(@RequestBody User user) {return "Hello world:" + user.toString();}}Filter相关代码:import lombok.extern.slf4j.Slf4j;import org.springframework.core.annotation.Order;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;@Slf4j@Order(1)@WebFilter(filterName = "MyFilter1", urlPatterns = "/test1")public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {("My filter log 1");chain.doFilter(request, response);}}import lombok.extern.slf4j.Slf4j;import org.springframework.core.annotation.Order;import ponent;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;@Slf4j@Order(2)@WebFilter(filterName = "MyFilter2", urlPatterns = "/test2")public class MyFilter2 implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {("My filter log 2");chain.doFilter(request, response);}}核⼼的代码如上,相关的请求Filter处理如下:/ : 两个Filter都不触发/test1 : 触发MyFilter1/test2 : 触发MyFilter2符合我们的使⽤预期,接下来我们到源码中探索:1.Filter是如何初始化的2.Filter是如何对应相关的URL请求的源码解析探索时是直接在MyFilter类打上断点,⼀步步探索堆栈,得到的相关源码如下Filter初始化⾸先是找到Filter相关类获取并遍历的相关代码下⾯的函数中,遍历获得了系统内置的和我们⾃⼰定义的Filter(如何获取的细节先不深究,在这⾥能得到所有的Filter)# ServletWebServerApplicationContext.classprivate void selfInitialize(ServletContext servletContext) throws ServletException {this.prepareWebApplicationContext(servletContext);this.registerApplicationScope(servletContext);WebApplicationContextUtils.registerEnvironmentBeans(this.getBeanFactory(), servletContext);// 得到了所有的Filter,遍历处理Iterator var2 = this.getServletContextInitializerBeans().iterator();while(var2.hasNext()) {ServletContextInitializer beans = (ServletContextInitializer)var2.next();beans.onStartup(servletContext);}}接下来来到添加注册Filter相关的代码部分# AbstractFilterRegistrationBean.classprotected void configure(Dynamic registration) {super.configure(registration);EnumSet<DispatcherType> dispatcherTypes = this.dispatcherTypes;if (dispatcherTypes == null) {T filter = this.getFilter();if (ClassUtils.isPresent("org.springframework.web.filter.OncePerRequestFilter", filter.getClass().getClassLoader()) && filter instanceof OncePerRequestFilter) { dispatcherTypes = EnumSet.allOf(DispatcherType.class);} else {dispatcherTypes = EnumSet.of(DispatcherType.REQUEST);}}Set<String> servletNames = new LinkedHashSet();Iterator var4 = this.servletRegistrationBeans.iterator();// 这部分代码作⽤尚不明确,留待以后探索while(var4.hasNext()) {ServletRegistrationBean<?> servletRegistrationBean = (ServletRegistrationBean)var4.next();servletNames.add(servletRegistrationBean.getServletName());}servletNames.addAll(this.servletNames);if (servletNames.isEmpty() && this.urlPatterns.isEmpty()) {// 系统默认的都⾛的这部分处理,拦截路径默认都是:/**registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, DEFAULT_URL_MAPPINGS);} else {if (!servletNames.isEmpty()) {registration.addMappingForServletNames(dispatcherTypes, this.matchAfter, StringUtils.toStringArray(servletNames));}// 我们⾃定义的都都了这⾥,拦截路径就是我们配置的:/test1,/test2if (!this.urlPatterns.isEmpty()) {registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, StringUtils.toStringArray(this.urlPatterns));}}}在上⾯的代码中,我们看到了拦截路径的配置有两个⽅式:servletNamesurlPatterns接着跟下去,下降就是将Filter添加# ApplicationFilterRegistration.javapublic void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter,String... urlPatterns) {FilterMap filterMap = new FilterMap();filterMap.setFilterName(filterDef.getFilterName());if (dispatcherTypes != null) {for (DispatcherType dispatcherType : dispatcherTypes) {filterMap.setDispatcher(());}}// Filter添加的相关代码if (urlPatterns != null) {// % decoded (if necessary) using UTF-8for (String urlPattern : urlPatterns) {filterMap.addURLPattern(urlPattern);}if (isMatchAfter) {context.addFilterMap(filterMap);} else {context.addFilterMapBefore(filterMap);}}// else error?}上⾯的代码中,Filter添加有两处代码:⼀个是添加到Map中,⼀个是context中,后者好像还是有其他道道,后⾯继续研究看看到这⾥,Filter就初始化完成了,下⾯看看使⽤⽅⾯的代码Filter匹配添加在⽇常开发中,Filter我们都会配置相关的匹配路径,不是所有的请求都进⾏过滤,那这块的匹配是怎么的?接下来就发起请求,探索Filter 的匹配添加下⾯的代码是核⼼的Filter匹配处理,但前⾯的触发调⽤⽬前暂时还没有梳理清楚,Wrapper好像挺关键的,暂时忽略它,先看Filter匹配处理相关的# ApplicationFilterFactory.javapublic static ApplicationFilterChain createFilterChain(ServletRequest request,Wrapper wrapper, Servlet servlet) {......// Acquire the filter mappings for this ContextStandardContext context = (StandardContext) wrapper.getParent();// 获取Filter,得到上⾯初始化的FilterFilterMap filterMaps[] = context.findFilterMaps();// If there are no filter mappings, we are doneif ((filterMaps == null) || (filterMaps.length == 0)) {return filterChain;}// Acquire the information we will need to match filter mappingsDispatcherType dispatcher =(DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);// 请求的路径String requestPath = null;Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);if (attribute != null){requestPath = attribute.toString();}String servletName = wrapper.getName();// 在这⾥就进⾏匹配了// Add the relevant path-mapped filters to this filter chainfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersURL(filterMap, requestPath)) {continue;}ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig == null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Add filters that match on servlet name secondfor (FilterMap filterMap : filterMaps) {if (!matchDispatcher(filterMap, dispatcher)) {continue;}if (!matchFiltersServlet(filterMap, servletName)) {continue;}ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName());if (filterConfig == null) {// FIXME - log configuration problemcontinue;}filterChain.addFilter(filterConfig);}// Return the completed filter chainreturn filterChain;}// 上⾯的触发调⽤后,就来到了下⾯的将Filter添加到列表中的相关diam# ApplicationFilterChain.javavoid addFilter(ApplicationFilterConfig filterConfig) {// Prevent the same filter being added multiple timesfor(ApplicationFilterConfig filter:filters) {if(filter==filterConfig) {return;}}if (n == filters.length) {ApplicationFilterConfig[] newFilters =new ApplicationFilterConfig[n + INCREMENT];System.arraycopy(filters, 0, newFilters, 0, n);filters = newFilters;}filters[n++] = filterConfig;}上⾯的就是核⼼的Filter匹配添加的核⼼代码,值得注意的点有下⾯⼏个:会被匹配添加两次匹配有下⾯三种⽅式:matchDispatcher(filterMap, dispatcher)matchFiltersURL(filterMap, requestPath)matchFiltersServlet(filterMap, servletName)这⾥就有下⾯两点疑问了:为啥需要将两次匹配分开:是为了前后Filter区分?两次Filter循环匹配,好像就是匹配路径requestPath和匹配ServletName的区别,两者有何不同,为啥需要分开?关于上⾯的疑问⽬前我也没找到确定的线索,后⾯的探索中,应该能把它补上经过上⾯的Filter匹配,请求的Filter就初始化好了,下⾯就进⼊到处理调⽤环节# ApplicationFilterChain.javapublic void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException {if( Globals.IS_SECURITY_ENABLED ) {final ServletRequest req = request;final ServletResponse res = response;try {java.security.AccessController.doPrivileged((java.security.PrivilegedExceptionAction<Void>) () -> {internalDoFilter(req,res);return null;});} catch( PrivilegedActionException pe) {......}} else {// 调⽤触发internalDoFilter(request,response);}}private void internalDoFilter(ServletRequest request,ServletResponse response)throws IOException, ServletException {// Call the next filter if there is oneif (pos < n) {ApplicationFilterConfig filterConfig = filters[pos++];try {// 获取当前FilterFilter filter = filterConfig.getFilter();if (request.isAsyncSupported() && "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);}if( Globals.IS_SECURITY_ENABLED ) {final ServletRequest req = request;final ServletResponse res = response;Principal principal =((HttpServletRequest) req).getUserPrincipal();Object[] args = new Object[]{req, res, this};SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);} else {// 调⽤触发filter.doFilter(request, response, this);}} catch (IOException | ServletException | RuntimeException e) {......}return;}// 下⾯的代码有疑似结束Filter,触发请求函数处理相关的代码。
J2EE 课程设计实训项目《蓝梦网上商城》——应用J2EE Filter实现Spring框架中“Open Session in View模式”
J2EE 课程设计实训项目——《蓝梦网上商城》——应用J2EE Filter过滤器组件实现Spring框架中的“Open Session in View模式”1.1.1应用J2EE Filter过滤器组件实现Spring框架中的“Open Session in View模式”由于本项目是Struts +Spring +Hibernate三者相互整合,同时由于Struts中的ContextLoaderPlugIn组件与OpenSessionInViewFilter组件之间产生了冲突,因此在本项目中放弃了OpenSessionInViewFilter组件,而采用标准的Filter组件来实现“Open Session in View”。
1、对本项目中的HibernateUtil.java代码进行修改(1)添加下面的黑体部分的代码package com.px1987.webshop.dao.util;import org.hibernate.*;import org.hibernate.cfg.*;public class HibernateUtil{private static final SessionFactory sessionFactory;/* 静态初始器,当JVM(Java虚拟机)加载HibernateUtil类时,会执行该静态代码块。
*/static{try{ // Create the SessionFactorysessionFactory = new Configuration().configure().buildSessionFactory();/*也可以采用下面的方式Configuration hibernateConfiguration=new Configuration();sessionFactory = hibernateConfiguration.configure().buildSessionFactory();*/}catch (Throwable ex){throw new ExceptionInInitializerError(ex);}}public static final ThreadLocal threadLocal = new ThreadLocal(); public static final ThreadLocal tLocaltx = new ThreadLocal(); public static Session currentSession(){Session currentSession = (Session) threadLocal.get();if (currentSession == null){currentSession = sessionFactory.openSession();threadLocal.set(currentSession);}return currentSession;}public static void closeSession(){Session currentSession = (Session) threadLocal.get();if (currentSession != null){currentSession.close();}threadLocal.set(null);}public static void beginTransaction(){Transaction tx = (Transaction) tLocaltx.get();try{if (tx == null) {tx = currentSession().beginTransaction();tLocaltx.set(tx);}}catch (HibernateException e) {throw e;}}public static void commitTransaction(){Transaction tx = (Transaction) tLocaltx.get();try{if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())mit();tLocaltx.set(null);}catch (HibernateException e){throw e;}}public static void rollbackTransaction(){Transaction tx = (Transaction) tLocaltx.get();try{tLocaltx.set(null);if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){tx.rollback();}}catch (HibernateException e){throw e;}}}(2)目的提供完整的事务实现的控制。
OpenSessionInViewFilter源码分析
OpenSessionInViewFilter源码分析在之前我写的一篇文章/aspdao/archive/2010/04/11/5472955.a spx详述了如何配置Hibernate懒加载当时我觉得我已经会配置Hibernate的懒加载了,但是,在最近做的课题项目中,相同版本的SSH,一样的配置,却发现懒加载部分成功,我觉得非常的诧异,以为Hibernate映射配置文件*.hbm.xml中设置不对,但是却无功而返。
在网上搜索了许久,还是没有得到想要的答案,最终促使我去读Spring和Hibernate的源码,了解OpenSessionInViewFilter究竟是如何工作的,以及项目中出错的地方为什么session被关闭掉了,什么时候由谁关闭的。
从书上我了解到Session接口是Hibernate向应用程序提供的操纵数据库的最主要接口,它提供了基本的保存、更新、删除和加载Java对象的方法。
Session具有一个缓存,位于缓存中的对象成为持久化对象,它和数据库中的相关记录对应,Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQL语句,来同步更新数据库,这一过程叫清理缓存。
Hibernate把对象分为4种状态:持久化状态、临时状态、游离状态和删除状态。
临时状态:刚用new语句创建,还能没有被持久化,并且不处于Session的缓存中。
处于临时状态的Java对象被称为临时对象。
持久化状态:已经被持久化,并且加入到Session的缓存中。
处于持久化状态的Java对象被称为持久化对象。
删除状态:不再处于Session的缓存中,并且Session已经计划将其从数据库中删除。
处与删除状态的对象被称为删除对象。
游离状态:已经被持久化,但不再处于Session的缓存中。
处于游离状态的Java对象被称为游离对象。
在其他文章中找到的图片,很直观。
废话少说,切入正题,在开发SSH项目时,其实并不直接接触到Hibernate的Session,正常的步骤是,先搭建SSH 框架,之后设计数据库,再根据数据库逆向工程生成相应的Bean和DAO,接下来根据具体需要将DAO封装成Service 供业务逻辑层使用,至始至终都没有显式的创建Session对象,也没有手动关闭它,但是no session or session closed 却是最常遇到的问题。
Servlet中的过滤器(拦截器)Filter与监听器Listener的作用和区别
Servlet中的过滤器(拦截器)Filter与监听器Listener的作用和区别1. 过滤器(Filter)的作用和用途:过滤器用于截取请求和响应,可以在请求到达目标资源之前预处理请求,也可以在响应返回给客户端之前对响应进行处理。
过滤器可以对请求和响应进行统一的处理,例如验证用户的登录状态、设置字符编码、限制请求的访问等。
过滤器的主要特点:- 过滤器的配置和初始化是在web.xml文件中进行的。
-过滤器可以通过设置多个过滤器链来实现不同的目的。
-过滤器可以通过链式调用的方式实现多个过滤器的集成。
-过滤器可以修改请求的参数、头部信息或者重定向到其他资源。
2. 监听器(Listener)的作用和用途:监听器用于监听Servlet中发生的事件和动作,并作出相应的处理。
监听器可以监听到Web应用的生命周期事件(如应用的启动和关闭)、会话的创建和销毁事件、请求的到达和离开等。
通过监听Servlet的事件,可以在事件发生前、发生后或者发生中进行相关操作,用于处理这些事件。
监听器的主要特点:-监听器可以通过注解或者配置文件的方式进行配置和初始化。
-监听器可以监听多个事件,根据事件的类型进行不同的处理。
-监听器可以访问和修改请求和响应对象。
-监听器可以获取到应用的初始化参数、会话信息等。
区别:- 过滤器(Filter)主要用于拦截请求和响应,可以对其进行预处理和后处理,常用于权限验证、请求包装、字符编码设置和URL重定向等。
而监听器(Listener)主要用于监听特定的事件和动作,常用于记录日志、统计在线人数、初始化和销毁操作等。
- 过滤器是在Servlet调用之前进行处理,通过链式调用的方式实现多个过滤器的集成。
而监听器是在Servlet处理过程中监听特定事件的发生,对事件进行相应的处理。
-过滤器可以修改请求和响应对象,而监听器只能获取和监听这些对象。
-过滤器可以针对多个URL进行配置,而监听器是全局的,对整个应用进行监听。
sessionmanagementfilter过滤器的用法 -回复
sessionmanagementfilter过滤器的用法-回复SessionManagementFilter是一个用于管理用户会话的过滤器。
它可以帮助开发人员在web应用程序中有效地管理和控制用户会话的生命周期。
在本篇文章中,我将详细介绍SessionManagementFilter的用法,包括如何配置和使用它。
第一步:引入依赖在开始使用SessionManagementFilter之前,首先需要在项目的配置文件中引入相关的依赖。
SessionManagementFilter通常是作为Spring Security框架的一部分使用的,因此需要引入Spring Security相关的依赖。
可以通过Maven或Gradle等构建工具在项目中添加以下依赖:xml<! Spring Security ><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>第二步:配置过滤器配置SessionManagementFilter需要在项目的配置文件中进行相关的配置。
通常,可以在application.properties或application.yml文件中进行配置。
首先,需要配置SessionManagementFilter的URL模式。
可以通过以下方式配置过滤器的URL模式:yamlspring:security:filter:session-management:session-authentication-strategy-ref: changeSessionIdinvalid-session-url: /login在上述配置中,通过session-authentication-strategy-ref属性指定会话认证策略,通过invalid-session-url属性指定会话无效时的重定向URL。
sessionmanagementfilter过滤器的用法
sessionmanagementfilter过滤器的用法Session Management Filter 过滤器是一种用于管理用户会话的Web 过滤器。
它通常用于跟踪用户会话,以便在用户访问应用程序时保持其状态。
要使用Session Management Filter 过滤器,首先需要在Web 应用程序中添加相应的依赖。
这通常涉及到将过滤器添加到项目的依赖项中,以便将过滤器添加到项目的Web 配置中。
一旦依赖项已添加,就可以在Web 配置文件中配置Session Management Filter 过滤器。
这通常涉及将过滤器添加到Web 应用程序的配置文件(如web.xml)中。
在配置文件中,需要指定过滤器的名称、类名以及任何其他必要的属性。
在过滤器被正确配置后,当用户访问应用程序时,Session Management Filter 过滤器将拦截用户的请求。
过滤器将检查请求中的会话信息,并在必要时创建或恢复会话。
这样,应用程序就能够跟踪用户的活动并保持其状态。
需要注意的是,Session Management Filter 过滤器仅用于管理会话。
它不负责处理用户的身份验证或授权。
这意味着在使用Session Management Filter 过滤器时,可能还需要使用其他安全过滤器来处理身份验证和授权问题。
总之,Session Management Filter 过滤器是一种用于管理用户会话的Web 过滤器,它可以帮助应用程序跟踪用户的活动并保持其状态。
正确配置和使用Session Management Filter 过滤器是确保Web 应用程序能够提供一致用户体验的关键。
1。
关于使用Spring导致c3p0数据库死锁问题
这个问题我实在是为整个springsource 的员工蒙羞如果大家使用spring 控制事务,使用Open Session In View 模式,com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource fromcom.mchange.v2.resourcepool.BasicResourcePool-- timeout at awaitAvailable()com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetecto r -- APPARENT DEADLOCK!!!还有诸如之类的若干c3p0 报出的错误,对于流量稍大一点的网站,一般都会出现当然,我确切的知道其原因是什么。
我只是想知道这个巨大的问题为什么这么多年过去了,仍旧在反复的不断地恼人的无解的一再发生。
我花了些时间google了一下,发现搜索"com.mchange.v2.resourcepool.TimeoutException" 这个字符串,前5页都没有给出正确答案。
有一些解决方案,我称为workaround,并不是solution,例如workaround1:<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。
Default: 3 --><property name="acquireIncrement" value="5"/>workaround2:是Spring中配置c3p0的时候,有一个配置属性是checkoutTimeout,把这个配置属性去掉就正常了。
好了,我来评价下这两种workaround第一种:这么搞下去,你的数据库连接数迟早会用光,到时结果是一样的,好比得了癌症这样做只是让你晚死几年。
跟我学Hibernate框架技术——Open Session in View模式的实现示例
1 杨教授工作室,版权所有,盗版必究, 1/22页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
1.1
பைடு நூலகம்
Hibernat 框架中的 Open Session in View 模式的实现示例
1.1.1 体验和理解 Hibernat 中的 Lazy Initialization(延迟加载)过程 1、Hibernat 中的 Lazy Initialization(延迟加载)过程 (1)在 Hibernate 手册中是这样描述 Lazy Initialization-延迟加载的 集合(不包括数组)是可以延迟初始化的,意思是仅仅当应用程序需要访问时,才载入他们 的值-----只在一个对象调用它的一对多或多对多关系时才将关联的目标对象读取出来。对于 使用者来说,初始化是透明的, 因此应用程序通常不需要关心这个(事实上,透明的延迟加 载也就是为什么 Hibernate 需要自己的集合实现的主要原因)。 (2)延迟加载的优点 非延迟加载在加载时获取对象本身以及它关联的所有对象。这可能导致在获取一个实例 时,执行成百上千的 select 语句。当使用双向关联时,这个问题被放大,常常出现初始化请 求时,整个数据库都被载入。 而如果应用延迟加载,则只需要进行很少的数据库操作请求,因此会得到比较明显的性 能提升。 (3)延迟加载的缺省设置 如果我们不描述,则 Lazy 的属性为 true----即使用延迟加载!在 Hibernate 中,集合类的 映射可以延迟初始(Lazy Initialization),也就是在真正索取該对象的属性时,才向数据库查 詢。 (4)注意的问题(或者要求) 是在同一次会话过程中保持的 使用延迟初始化的另一个问题是,由于在需要时才会去查询数据库表,所以 session 不 能 关 闭 , 如 果 在 session 关 闭 后 , 再 去 要 求 被 关 联 的 实 体 , 将 会 发 生 LazyInitializationException 异常。 这会成为通过使用 DAO 模式将持久层抽象出来时的一个主要问题-----因为, 我们为了将 持久化机制完全地抽象出来,一般在实际应用中都是将所有的数据库逻辑,包括打开或关闭
在Spring与Hibernate相互整合的应用中应用Spring中 “Open Session in View模式”
1.1在Spring与Hibernate相互整合的应用中应用Spring中“Open Session in View模式”1.1.1应用OpenSessionInViewInterceptor插件1、Spring提供了OpenSessionInViewerFilter和OpenSessionInViewInterceptor两种组件(1)功能使用它们中的任一个都能获得同样的功能。
(2)两者唯一不同点其中interceptor在Spring容器中运行,并且在web应用的上下文中配置(WebApplicationContext);而Fitler在Spring前就已经运行,并且需要在web.xml中配置。
不管使用哪一个,他们都会在请求绑定到Session的当前线程期间打开Hibernate Session。
(3)实现的原理Open Session In View在request把session绑定到当前thread期间一直保持hibernate session在open状态,使session在request的整个期间都可以使用,如在View层里PO也可以lazy loading数据。
当View 层逻辑完成后,才会通过Filter的doFilter方法或Interceptor的postHandle方法自动关闭session。
(4)HibernateDaoSupport透明地使用Hibernate 的Session一旦绑定到线程,打开的Hibernate 的Session能被DAO的实现类透明地使用。
Session 会持续打开允许延迟加载访问数据库。
一旦View逻辑完成,Hibernate 的Session会被关闭,无论是在Filter的doFilter方法中还是在Interceptor的postHandle方法中。
2、Interceptor配置示例此时可以使用Spring的AOP配置,将这个Interceptor配置到我们所需要的层次上去。