阅读 22

SpringBoot项目实战经验之HandlerInterceptorAdapter实现自定义拦截器

此文章已同步更新至我的个人博客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模拟请求,查看日志: