SpringBoot之Interceptor拦截器注入使用

相关文章:
SpringBoot 之AOP切面的使用
SpringBoot之Listener注册到Spring容器中的多种方法
SpringBoot之Filter过滤器的实现及排序问题
SpringBoot 之多个过滤器(Filter) ,监听器(Listener),切面(AOP),拦截器(Interceptor)的指定排序问题总结篇

springboot中实现拦截器方式

实现方式

实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter 抽象类

两者区别

HandlerInterceptorAdapter 实现AsyncHandlerInterceptor接口,AsyncHandlerInterceptor接口 继承HandlerInterceptor接口。AsyncHandlerInterceptor接口多了一个afterConcurrentHandlingStarted方法

创建一个拦截器实现HandlerInterceptor接口

在jdk1.8之后,只需要实现自己需要的方法。因为接口有默认实现。

@Component
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理
     * 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
   */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("方法开始前拦截.........");
        //业务代码 返回false或者true
        return false;
    }
     /**
     * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("方法返回后拦截.........");
    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("方法结束后拦截.........");
    }
}

创建一个拦截器继承HandlerInterceptorAdapter类

@Component
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理
     * 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
   */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("方法开始前拦截.........");
        //业务代码 返回false或者true
        return false;
    }
     /**
     * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("方法返回后拦截.........");
    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("方法结束后拦截.........");
    }
    /**
    * 如果返回一个current类型的变量,会启用一个新的线程。执行完preHandle方法之后立即会调用afterConcurrentHandlingStarted,然后新线程再以次执行
    */
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("do something.........");
        super.afterConcurrentHandlingStarted(request, response, handler);
    }
}

创建配置类来管理拦截器,并将之前的拦截器注入其中

两种方式,实现 WebMvcConfigurer 或者继承 WebMvcConfigurationSupport 两者没什么区别,看项目的选择。

@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurationSupport {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则,/**表示拦截所有请求
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
        .excludePathPatterns("/stuInfo/getAllStuInfoA","/account/register");  
    }
}

多个拦截器执行顺序

多个拦截器的执行顺序按照你的代码代码添加顺序,先添加后执行。

在未设置order方法值时:
registry.addInterceptor(repeatPutInterceptor) // 1
registry.addInterceptor(refererInterceptor) // 2
registry.addInterceptor(loginAuthInterceptor) //3

针对于preHandle 执行顺序为:1->2->3
针对于postHandle执行顺序为:3->2->1
针对于afterCompletion执行顺序为:3->2->1

设置order值时:此时能实现自定义顺序
registry.addInterceptor(repeatPutInterceptor).order(1) // 1
registry.addInterceptor(loginAuthInterceptor).order(3) //2
registry.addInterceptor(refererInterceptor).order(2) // 3

针对于preHandle 执行顺序为:1->3->2
针对于postHandle执行顺序为:2->3->1
针对于afterCompletion执行顺序为:2->3->1

源码出处:InterceptorRegistry类
protected List<Object> getInterceptors() {
   return this.registrations.stream()
         .sorted(INTERCEPTOR_ORDER_COMPARATOR)
         .map(InterceptorRegistration::getInterceptor)
         .collect(Collectors.toList());
}
private static final Comparator<Object> INTERCEPTOR_ORDER_COMPARATOR =
      OrderComparator.INSTANCE.withSourceProvider(object -> {
         if (object instanceof InterceptorRegistration) {
            return (Ordered) ((InterceptorRegistration) object)::getOrder;
         }
         return null;
      });
排序问题

添加@order注解,和实现Ordered 接口都无法实现自定义顺序的。只能在配置类中注入拦截器的时候添加order或者使用代码顺序来自定义排序

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值