spring拦截器的实现方式和执行顺序。(用springboot快速搭建个web项目,用于测试)
拦截器有两种方式,继承HandlerInterceptorAdapter  或者实现HandlerInterceptor 如下三个拦截器
@Componentpublic class FirstInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("FirstInterceptor: preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {System.out.println("FirstInterceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {System.out.println("FirstInterceptor: afterCompletion");}}
@Componentpublic class SecondInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {System.out.println("SecondInterceptor: preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("SecondInterceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("SecondInterceptor: afterCompletion");}}
@Componentpublic class ThirdInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("ThirdInterceptor: preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("ThirdInterceptor: postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("ThirdInterceptor: afterCompletion");}}
注册拦截器
@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//FirstInterceptor 拦截除了/test2/** 以外的所有请求InterceptorRegistration first = registry.addInterceptor(new FirstInterceptor());first.addPathPatterns("/**");first.excludePathPatterns("/test2/**");//SecondInterceptor 拦截所有的请求InterceptorRegistration second = registry.addInterceptor(new SecondInterceptor());second.addPathPatterns("/**");//ThirdInterceptor 拦截所有的请求InterceptorRegistration third = registry.addInterceptor(new ThirdInterceptor());third.addPathPatterns("/**");}}
新建个请求,测试拦截器
@RestControllerpublic class IndexController {@RequestMapping("/test1/index")public String index1() {System.out.println("IndexController test1/index");return "test1 index";}@RequestMapping("/test2/index")public String index2() {System.out.println("IndexController test2/index");return "test2 index";}}
正常情况下执行test1/index,查看拦截器执行情况
FirstInterceptor: preHandleSecondInterceptor: preHandleThirdInterceptor: preHandleIndexController test1/indexThirdInterceptor: postHandleSecondInterceptor: postHandleFirstInterceptor: postHandleThirdInterceptor: afterCompletionSecondInterceptor: afterCompletionFirstInterceptor: afterCompletion
结论:
执行顺序按照注册的顺序来执行,如果我们有N个拦截器,那么执行顺序如下:
首先顺序执行N个拦截器的preHandle()方法
1:preHandle()—>2:preHandle()…—>n:preHandle()
然后执行我们的controller
test1/index
紧接着倒序执行postHandle()方法
n:postHandle()—>n-1:postHandle()…—>1:postHandle()
最后倒序执行afterCompletion()方法
n:afterCompletion()—>n-1:afterCompletion()…—>1:afterCompletion()
如果其中一个拦截器返回false,例如我们让ThirdInterceptor返回false,那么执行情况是
FirstInterceptor: preHandleSecondInterceptor: preHandleThirdInterceptor: preHandleSecondInterceptor: afterCompletionFirstInterceptor: afterCompletion
结论:
执行顺序按照注册的顺序来执行,如果我们有N个拦截器,第m个拦截器拦截后返回false,那么执行顺序如下:
首先顺序执行到第m个拦截器的preHandle()方法
1:preHandle()—>2:preHandle()…—>m:preHandle()
此时第m个拦截器成功拦截了请求,返回false,此时便会倒序执行前面的afterCompletion()方法
m-1:afterCompletion()—>m-2:afterCompletion()…—>1:afterCompletion()
