SprigMVC拦截器HandlerInterceptor
观前提示:
本文所使用的Eclipse版本为Photon Release (4.8.0),JDK版本为1.8.0_141,Tomcat版本为9.0.12。
1.简介
SpringFramework的处理器拦截器,用于处理器进行预处理和后处理。应用与以下场景:
-
日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
-
权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
-
性能监控:典型的是慢日志。
2.拦截器HandlerInterceptor
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract interface HandlerInterceptor
{
public abstract boolean preHandle(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse, Object paramObject)
throws Exception;
public abstract void postHandle(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse, Object paramObject, ModelAndView paramModelAndView)
throws Exception;
public abstract void afterCompletion(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse, Object paramObject, Exception paramException)
throws Exception;
}
-
preHandle:预处理回调,在处理器处理之前回调。只有该方法返回true,才会继续执行后续的Interceptor和Controller,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法。
-
postHandle:该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用,可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
-
afterCompletion:该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。
3.拦截器适配器HandlerInterceptorAdapter
如果实现HandlerInterceptor接口的话,需要全部实现上述的三个方法,但是我们可以通过HandlerInterceptorAdapter,并不需要全部实现,仅需要实现我们所需要的方法即可。
package org.springframework.web.servlet.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public abstract class HandlerInterceptorAdapter
implements AsyncHandlerInterceptor
{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception
{
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception
{
}
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
}
}
4.运行流程
4.1 流程1:preHandle处理结果全部为true
4.2 流程2:preHandle处理结果含有false时
5 例子
配置3个拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/test"/>
<bean class="cn.com.mydemo.interceptor.TestHandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/test"/>
<bean class="cn.com.mydemo.interceptor.TestHandlerInterceptor2"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/test"/>
<bean class="cn.com.mydemo.interceptor.TestHandlerInterceptor3"></bean>
</mvc:interceptor>
</mvc:interceptors>
package cn.com.mydemo.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class TestHandlerInterceptor1 extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("-----------------afterCompletion1-----------------");
super.afterCompletion(request, response, handler, ex);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("-----------------postHandle1-----------------");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("-----------------preHandle1-----------------");
return true;
}
}
package cn.com.mydemo.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class TestHandlerInterceptor2 extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("-----------------afterCompletion2-----------------");
super.afterCompletion(request, response, handler, ex);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("-----------------postHandle2-----------------");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("-----------------preHandle2-----------------");
return true;
}
}
package cn.com.mydemo.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class TestHandlerInterceptor3 extends HandlerInterceptorAdapter {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("-----------------afterCompletion3-----------------");
super.afterCompletion(request, response, handler, ex);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("-----------------postHandle3-----------------");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("-----------------preHandle3-----------------");
return true;
}
}
主方法
@RequestMapping(value = "/test")
public void testHandlerInterceptor() {
System.out.println("-----------------Main Function-----------------");
}
5.1 3个拦截器preHandle全部返回true
5.2 3个拦截器preHandle分别返回true,true,false时
6.总结运行流程
- 拦截器按照Spring配置文件中定义的顺序执行。
- 会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。
- 然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。
- 在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)