Archive for October, 2020

Springboot 拦截器的坑 WebMvcConfigurationSupport 失效

October 16th, 2020

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

环境:

springboot 2.x

spring 5.x

===================

拦截器创建的几种方式

  • extends WebMvcConfigurationSupport
  • implements WebMvcConfigurer

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

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

那多个 继承 WebMvcConfigurationSupport 为啥只有一个生效呢,答案在这个类WebMvcAutoConfiguration 的 ConditionalOnMissingBean 注解,只实例化一个Bean,多个继承也只有一个生效。
再看下 addInterceptors 啥时候触发的,获取拦截器的时候,获取过就不再获取了,所以 addInterceptors 在项目启动触发才有效。而 getInterceptors 这个方法是在 handerMapping映射的时候触发的(比如 RequestMappingHandlerMapping、BeanNameUrlHandlerMapping)。

解决方案

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

  • 不继承 WebMvcConfigurationSupport ,拦截器全部通过实现 WebMvcConfigurer 接口(推荐)
  • 只继承一次 WebMvcConfigurationSupport ,在这个类管理所有的拦截器(不推荐,耦合性太高)
  • 针对我的场景,通过过滤器实现的。注入的代码就不贴了,before 和 fater 方法实现了类似拦截器的 preHandle 和 afterCompletion。有一点需要注意的是指定过滤器的排序(默认已经是最高了,可以忽略),由于过滤器是链式调用,如果想当拦截器用,必须指定最先加载,还有就是过滤器会拦截静态资源,做好对静态资源的放行。

 

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

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