spring boot拦截器默认有:
- HandlerInterceptorAdapter
- AbstractHandlerMapping
- UserRoleAuthorizationInterceptor
- LocaleChangeInterceptor
- ThemeChangeInterceptor
要想定义一个Interceptor非常简单,这里以HandlerInterceptor接口为例:类实现Spring的HandlerInterceptor接口,或者是这个类继承实现了HandlerInterceptor接口的HandlerInterceptorAdapter类。
上代码:
-
TestInterceptorAdapter
@Component
public class TestInterceptorAdapter implements HandlerInterceptor {
private ThreadLocal<Long> startTime = new ThreadLocal<Long>();
@Autowired
private RedisUtil redisUtil;
/**
* 在请求处理之前进行调用(Controller方法调用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("在请求处理之前进行调用(Controller方法调用之前)");
return true;// 只有返回true才会继续向下执行,返回false取消当前请求
}
/**
* 在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("整个请求结束之后进行调用(主要用于资源清理工作)");
}
/**
*请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
}
}
-
TestConfigurerAdapter
/**
* Description: 访问拦截器 拦截指定的请求.
*/
@Configuration
public class TestConfigurerAdapter extends WebMvcConfigurerAdapter {
@Autowired
private TestInterceptorAdapter testInterceptorAdapter;
//拦截排除项
private static String[] unInterceptor = new String[] {"/swagger-resources/**", "/**/exclude/**","/error"};
/**
* 访问拦截器 拦截指定的请求,添加拦截器方法
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加testInterceptorAdapter拦截器方法
registry.addInterceptor( apiInterceptorAdapter ).addPathPatterns("/**").excludePathPatterns( unInterceptor );
super.addInterceptors(registry);
}
}
-
详解
TestinTerceptorAdapter类实现的HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的:
(1)preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,该方法将在请求处理之前进行调用。当在一个应用中或者说是在一个请求中同时存在多个Interceptor时,这几个Interceptor是链式调用的。每个Interceptor的调用会根据它的声明顺序依次执行,而且最先执行的都是Interceptor中的preHandle方法,该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法。
(2)postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,该方法在请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后),且只有在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用,所以可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。
(3)afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法整个请求结束之后进行调用,也是只有在对应的Interceptor的preHandle方法的返回值为true时才会执行,这个方法的主要作用是用于进行资源清理工作的。
-
多个Interceptor执行顺序
如果这里有两个Interceptor,那么他们的执行顺序会是怎样的呢?这里借用其它博主的一张图来说明:
- 之前讲到过首先调用的是Interceptor的preHandle()方法,并且根据其声明顺序执行,所以这里第一步是先访问的MyInterceptor1中的preHandle()方法,当其返回true时才会调用MyInterceptor2中preHandle()方法。
- 当且仅当两个Interceptor的preHandle()方法都返回true才会调用postHanle()方法,但是这里的postHandle()方法被调用的方向跟preHandle是相反的。
- 最后同样当两个Interceptor的postHanle()都返回true时才会调用afterCompletion()方法。
注:小弟怕以后忘记,故将网络上大神的博文进行了一些杂糅,也打上了原创的标签,请勿见怪。