API: http://docs.spring.io/spring-framework/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html
DOCS: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-handlermapping-interceptor
Blog: http://haohaoxuexi.iteye.com/blog/1750680
Spring 的 Interceptor (拦截器)是通过 HandlerInterceptor 接口实现的。
package org.springframework.web.servlet; public interface HandlerInterceptor { boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
Spring 的 handle mapping(处理器映射)机制包含handler interceptors(处理拦截器),当你需要需要对某一请求应用特定的功能时,拦截器会变得很有用,例如身份检查。
位于处理映射中的拦截器必须实现 org.springframework.web.servlet 包下的 HandlerInterceptor 接口。这个定义了三个方法:
这三个方法为各种 preprocessing 和 postprocessing (前处理和后处理)提供了足够的灵活性。
说明:preHandle(…)方法返回一个布尔值,你可以使用这个方法来中断或继续执行 execution chain(执行链)。当此方法返回 true, handler 执行链会继续执行;当返回 false,DispatcherServlet 认为拦截器自身已经完成了对请求的处理(例如,呈现一个适当的视图),就不会继续执行其他拦截器,也不会执行执行链中的实际的 handler。
拦截 handler 的执行。在 HeandlerMapping 决定了一个合适的 handler 对象之后,但在 HandlerAdapter 调用 handler 之前被调用。
DispatcherServlet 处理 execution chain(执行链)中的 handler,执行链由数个拦截器组成,handler 在执行链的最后。通过此方法,每一个拦截器都可以决定放弃后面的执行链,典型地做法如:发送一个HTTP错误,或写入一个自定义响应。
返回值:
true:如果执行链要处理下一个拦截器或handler。否则,DispatcherServlet 假定此拦截器自己已处理了响应。
拦截 handler 的执行。在 HandlerAdapter 实际调用 handler 之后,但在 DispatcherServlet 渲染 view 之前被调用。可以暴露额外的 modle 对象到参数中的 ModelAndView。
DispatcherServlet 处理 execution chain(执行链)中的 handler,执行链由数个拦截器组成,handler 在执行链的最后。通过此方法,每一个拦截器都可以执行一个后处理,按执行链顺序的逆序执行。
完成请求处理之后的回调,在渲染 view 之后。将在任何 handler 执行结果上调用,因此允许做适当的资源清理。
注意:只在拦截器的 preHandle 方法成功执行完成且返回 true 时才被调用!
与 postHandle 方法一样。此方法按拦截器在执行链中的顺序逆序调用。因此第一个拦截器(的此方法)将在最后被调用。
public class FirstInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("FirstInterceptor ... preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("FirstInterceptor ... postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("FirstInterceptor ... afterCompletion"); } }
WebRequestInterceptor 是另外一个接口。原型是:
package org.springframework.web.context.request; public interface WebRequestInterceptor { void preHandle(WebRequest request) throws Exception; void postHandle(WebRequest request, ModelMap model) throws Exception; void afterCompletion(WebRequest request, Exception ex) throws Exception; }
在请求的 handler 调用之前拦截执行。
允许在此时准备上下文资源(比如 Hibernate Session),把它们暴露到 request attributes 中,或者暴露为 thread-local 对象。
在请求的 handler 成功执行之后,在 view 渲染之前,拦截执行。
允许在 handler 执行成功之后,修改上下文资源(例如:清除 Hibernate Session)。
view 渲染之后的回调。将在 handler 执行的结果上调用,因此允许此时做是的适当的资源释放。
注意:仅在此拦截器的 preHandle 方法成功执行完成的情况下被调用!
preHandle方法:方法的返回值为 void,不同于 HandlerInterceptor,一般被用于资源准备工作。可以调用 WebRequest 的 setAttribute(name, value, scope) 方法把相关资源放入 WebRequest 的属性中。其中的 scope 作用域值可以为:
postHandle方法:可以在这个方法里面通过改变数据模型 ModelMap 来改变数据的展示。参数:
afterCompletion方法:该方法会在整个请求处理完成,也就是在视图返回并被渲染之后执行。可以在方法中可以进行资源的释放操作。参数:
这里只介绍 XML 声明方式。
方式一 :
直接定义一个 Interceptor 实现类的bean对象。使用这种方式声明的 Interceptor 拦截器将会对所有的请求进行拦截。
<mvc:interceptors> <bean class="com.my.FirstInterceptor"/> </mvc:interceptors>
方式二 :
使用 mvc:interceptor 标签进行声明。使用这种方式进行声明的 Interceptor 可以通过 mvc:mapping 子标签来定义需要进行拦截的请求路径。
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/test/hello.do"/> <bean class="com.my.FirstInterceptor"/> </mvc:interceptor> </mvc:interceptors>