此文章已同步更新至我的个人博客https://simonting.gitee.io
SpringBoot中提供了HandlerInterceptorAdapter适配器供我们自定义拦截器,可以拦截自定义或所有的请求做相应的处理。
HandlerInterceptorAdapter中共有四个方法:
- preHandle :在Controller方法被调用前执行
- postHandle :在Controller方法调用后执行
- afterCompletion :在整个请求处理完成之后执行
- afterConcurrentHandlingStarted :用来处理异步请求,当Controller中有异步请求方法的时候会触发该方法。
实现步骤
自定义拦截器
继承HandlerInterceptorAdapter,重写方法(在实际项目中,可以按照实际的业务重写方法,不需要重写全部四个方法)
/**
* @Author zhangting
* @Desc 自定义拦截器
* @Date 2020/08/04
**/
@Component
@Slf4j
public class MyInterceptor1 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- preHandle(1) -----");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("----- postHandle(1) -----");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("----- afterCompletion(1) -----");
super.afterCompletion(request, response, handler, ex);
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- afterConcurrentHandlingStarted(1) -----");
super.afterConcurrentHandlingStarted(request, response, handler);
}
}
注册拦截器
实现WebMvcConfigurer,注册拦截器
/**
* @Author zhangting
* @Desc 注册拦截器
* @Date 2020/08/04
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor1 myInterceptor1;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor1);
}
}
上面实现的是自定义一个拦截器的情景,但是一般在实际项目中会需要自定义多个拦截器,那么这些拦截器的执行顺序又是如何确定的呢?拦截器内部的方法的执行顺序又是怎样的呢?
自定义多个拦截器
定义MyInterceptor2拦截器
/**
* @Author zhangting
* @Desc 自定义拦截器
* @Date 2020/08/04
**/
@Component
@Slf4j
public class MyInterceptor2 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- preHandle(2) -----");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("----- postHandle(2) -----");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("----- afterCompletion(2) -----");
super.afterCompletion(request, response, handler, ex);
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("----- afterConcurrentHandlingStarted(2) -----");
super.afterConcurrentHandlingStarted(request, response, handler);
}
}
将自定义的MyInterceptor2拦截器注册到容器中
/**
* @Author zhangting
* @Desc 注册拦截器
* @Date 2020/08/04
**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor1 myInterceptor1;
@Autowired
private MyInterceptor2 myInterceptor2;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor1);
registry.addInterceptor(myInterceptor2);
}
}
此时我们定义了两个拦截器,且注册的时候,先注册MyInterceptor1拦截器,再注册MyInterceptor2拦截器,接下来测试一下他们的执行顺序。
使用postman模拟请求,打印日志
结论
由测试结果可以得出:
- 拦截器的执行顺序_按照注册顺序_。
- 方法的执行顺序按照:preHandle()方法按照正序执行,postHandle()、afterCompletion()方法按照倒序执行。
自定义拦截URL
在注册拦截器如果不指定拦截的URL则默认所有的URL都会被拦截。我们也可以在注册拦截器时自定义该拦截器需要拦截的URL。
使用postman模拟请求,查看日志: