Lyscms+
登录注册
SpringBoot2拦截器实现失效及静态资源问题解决
原创SpringBoot2拦截器实现失效及静态资源问题解决

Java
image
亮月官方
2020-03-20 12:48:34
阅读数:1578
SpringBoot拦截器失效WebMvcConfigurerAdapter弃用

背景

最近在实现一个防止重复提交的组件时,由于项目是基于SringBoot2.0+搭建的,故需要基于SringBoot2.0+的拦截器实现,开始想到用AOP切面,但是好像无法动态设置切面范围,只能通过配置包名并且是在注解上写死(暂未发现代码配置方式),由于组件性质无法确定组件使用方的包名,需要全局性的拦截请求接口,所以拦截器是最好不过的选择。

看到最后应该有你想要的答案

准备

于是开始了前期的了解SpringBoot拦截器实现,开始搜索到实现是:

  1. 继承适配器类:WebMvcConfigurerAdapter
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
//实现拦截器 要拦截的路径以及不拦截的路径
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自定义拦截器,添加拦截路径和排除拦截路径

        registry.addInterceptor(new CustomInterceptor())
.addPathPatterns("/**").excludePathPatterns("/loginPage","/login");
}

注意:CustomInterceptor为下面的拦截器接口实现类

  1. 实现拦截器接口:HandlerInterceptor
public class CustomInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(InterceptorConfig.class);

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, 
                             HttpServletResponse response, Object o) throws Exception {
            //拦截接口方法执行前执行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, 
                           HttpServletResponse httpServletResponse, Object o, 
                           ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, 
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
           //拦截接口方法执行完毕后执行
    }
}

  1. 完毕,高兴的实现了去

问题

可是等实现中发现, WebMvcConfigurerAdapter类在编译器提示已经弃用,难受:),最难受的是过期还不在类上说明替换方案,于是到网上查询替换方案,查询到在SpringBoot2.0已经被弃用了,新增了一个WebMvcConfigurationSupport类来替代(包含了WebMvcConfigurerAdapter,以及更多的扩展),使用这个类的时候要注意一些地方:
我们都知道在使用spring boot映射静态资源路径的时候可以在application.properties中添加配置

spring.mvc.static-path-pattern = /static/**

这种写法在2.0之前 也就是在WebMvcConfigurerAdapter没有废弃 搭配使用的话是没有问题的(测试过是没有问题的),

但是在项目中我刚刚好用到了WebMvcConfigurationSupport类来配置拦截器,这时候启动项目时会发现映射根本没有成功,也就是说application.properties中添加配置的映射配置没有启动作用,

解决

然后我们会想到重写来进行映射,于是在本配置类中增加配置如下:


@Configuration
public class WebAppConfig extends WebMvcConfigurationSupport {
   
    //实现拦截器 要拦截的路径以及不拦截的路径
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自定义拦截器,添加拦截路径和排除拦截路径

        registry.addInterceptor(new CustomInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/loginPage","/login");
    }
   @Override
   protected void addResourceHandlers(ResourceHandlerRegistry registry) {
      registry.addResourceHandler("/sh/static/**").addResourceLocations("classpath:/static/");
      super.addResourceHandlers(registry);
   }
}

好,静态问题按照这个方式处理,但是又出现了新的问题:
其它的正常的所有业务接口api失效了,访问都出现404状态码,waht? 真实一波未平一波又起。

想安安静静的做个美男子就不行吗?

于是到网上查阅为什么呢?不查不知道一查吓一跳,继承WebMvcConfigurationSupport类会导致SringMVC的自动配置失效,waht?
这不是坑吗?经过查询官网说明,可以直接实现WebMvcConfigurer接口,基于java8 default特性不用全部实现里面所有方法,于是直接把继承WebMvcConfigurationSupport改为实现WebMvcConfigurer接口即可。

难受,拦截器还是不生效,waht?经过代码调试,确实没有到添加拦截那里,也就是下面方法根本没初始化执行:

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册自定义拦截器,添加拦截路径和排除拦截路径

        registry.addInterceptor(new CustomInterceptor())
                .addPathPatterns("/**").excludePathPatterns("/loginPage","/login");
    }

经过各种折腾:

  1. 将实现WebMvcConfigurer接口修改为继承WebMvcConfigurationSupport类,addInterceptors方法执行了,但是拦截器依然无效。

  2. 于是查询得知实现的拦截器类CustomInterceptor需要交给Spring容器管理,于是:

      @Bean
     public CustomInterceptor customInterceptor() {
         return new CustomInterceptor();
     }
    
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         //注册自定义拦截器,添加拦截路径和排除拦截路径
    
         registry.addInterceptor(customInterceptor())
                 .addPathPatterns("/**").excludePathPatterns("/loginPage","/login");
     }
    

    但是还是不行,替换为实现WebMvcConfigurer也不行

  3. 换用另外一种方式:在拦截器实现类CustomInterceptor上增加注解@Component 由于是组件,Spring在非启动类子包下的组件是扫描不到的(我的组件是非项目包路径下,单独的包名),于是又结合在启动类上增加@ComponentScan指定的扫描包路径,但是@ComponentScan和@SpringBootApplication注解不能共存,因为@SpringBootApplication已经包含了@ComponentScan,导致被覆盖,基本接口都失效了,但拦截器生效了

  4. 于是在@ComponentScan上增加了组件包名和项目应用包名。但现在基本接口生效了,但是拦截器失效了,waht?

晋级

这里尝试了半天,第二天又折腾了半天,想到是不是我项目有问题,于是单独起了一个demo服务集成我的这个防止重复提交组件,拦截器生效了,一起正常。这下锁定是我的项目的问题,但是是哪里的问题呢,于是走读查看所有配置问题,突然发现了另外一个地方还有一个配置使用了WebMvcConfigurationSupport类,导致了该配置被加载,后面的相同配置会失效,把这里的也改成实现WebMvcConfigurer即可,大功告成!问题解决。

一个人在年轻的时候浪费自己的才华与天赋是一件非常可惜的事情,文章最后更新于:2020-03-20 12:48:34

做个男人,做个成熟的男人,做个有城府的男人
记录在linux上使用Graphics2D进行添加水印的时候中文乱码问题解决
loading