springboot 拦截器的坑 WebMvcConfigurationSupport 失效

大家好,我是烤鸭:

今天遇到一个拦截器失效的问题,具体看源码分析下。

环境:

    springboot 2.x

    spring 5.x

1.  先说下业务场景

需求是对请求进入时和离开时对和线程id绑定,用的Threadlocal,现在有一个问题,利用拦截器的方式不生效。

2.   拦截器创建的几种方式

2.1 extends WebMvcConfigurationSupport

@Configuration
public class WebMvcAutoConfigurationAdapter extends WebMvcConfigurationSupport {

    @Autowired
    MapiHttpRequestInterceptor mapiHttpRequestInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration addInterceptor = registry.addInterceptor(mapiHttpRequestInterceptor);

        // 拦截配置
        addInterceptor.addPathPatterns("/**");
    }
}

@Component
class MapiHttpRequestInterceptor implements HandlerInterceptor{
}

2.2 implements WebMvcConfigurer

@Configuration
public class WebMvcAutoConfiguration3Adapter implements WebMvcConfigurer {

    @Autowired
    MapiHttpRequest3Interceptor mapiHttpRequestInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration addInterceptor = registry.addInterceptor(mapiHttpRequestInterceptor);

        // 拦截配置
        addInterceptor.addPathPatterns("/**");
    }
}

@Component
class MapiHttpRequest3Interceptor implements HandlerInterceptor{
    
}

先说下结论,如果项目中出现了一次 extends WebMvcConfigurationSupport ,其他的 extends WebMvcConfigurationSupport 和 implements WebMvcConfigurer 会失效 。

3.   看下源码为啥呢

先看下 WebMvcConfigurationSupport 这个类, addInterceptors 这个方法,默认继承的是 DelegatingWebMvcConfiguration,这个类就是获取 `所有 ` 实现 WebMvcConfigurer 的子类,调用他们的方法,如果有多个 通过实现 WebMvcConfigurer 创建的拦截器,是都可以生效的。

那多个 继承 WebMvcConfigurationSupport  为啥只有一个生效呢,答案在这个类WebMvcAutoConfiguration 的 ConditionalOnMissingBean 注解,只实例化一个Bean,多个继承也只有一个生效。

再看下 addInterceptors 啥时候触发的,获取拦截器的时候,获取过就不再获取了,所以 addInterceptors 在项目启动触发才有效。而 getInterceptors 这个方法是在 handerMapping映射的时候触发的(比如 RequestMappingHandlerMapping、BeanNameUrlHandlerMapping)。

4.   解决方案

针对不同的场景解决方案也不一样,我想到的有3个方案。

  • 不继承 WebMvcConfigurationSupport ,拦截器全部通过实现 WebMvcConfigurer 接口(推荐)
  • 只继承一次 WebMvcConfigurationSupport ,在这个类管理所有的拦截器(不推荐,耦合性太高)
  • 针对我的场景,我通过 过滤器实现的。注入的代码就不贴了,before 和 fater 方法实现了类似拦截器的 preHandle 和 afterCompletion。有一点需要注意的是指定过滤器的排序(默认已经是最高了,可以忽略),由于过滤器是链式调用,如果想当拦截器用,必须指定最先加载,还有就是过滤器会拦截静态资源,做好对静态资源的放行
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    if (servletRequest instanceof HttpServletRequest) {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        this.before(request);
        filterChain.doFilter(servletRequest, servletResponse);
        this.after();
    }
}
@Bean
public FilterRegistrationBean mapiXxxFilterRegister() {
    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setOrder(2147483647);
    filterRegistrationBean.setFilter(this.mapiXxxFilter);
    filterRegistrationBean.setName("filter-xxx");
    filterRegistrationBean.addUrlPatterns(new String[]{"/*"});
    return filterRegistrationBean;
}

这两篇文章也是类似的问题,大家也可以看下:

https://www.lyscms.info/blog/detail/33A55BEE2FD94E66B40990EA4967D3F7

https://blog.csdn.net/pengdandezhi/article/details/81182701

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烤鸭的世界我们不懂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值