站在巨人的肩膀上
Spring Boot 攔截器無效,不起作用
這個問題一般是解決
WebMvcConfigurerAdapter
過時問題造成的。導致這個問題可能有兩個原因:一個是攔截器寫錯了,另一個是攔截器配置錯了。
1、需求是這樣的
攔截所有的
api
請求,判斷其請求頭中的secret
參數是否正確,正確的請求才能訪問api
。
2、攔截器配置
需要先寫攔截器,然后再配置到
Spring Boot
環境中。
2.1、寫一個攔截器
在
Spring MVC
中,攔截器有兩種寫法:要么實現HandlerInterceptor
接口,要么實現WebRequestInterceptor
接口,具體內容請看這里詳述Spring MVC
框架中攔截器Interceptor
的使用方法。
而Spring Boot
也只是集成了Spring MVC
而已,所以攔截器的寫法還是一樣的。不一樣的是Spring MVC
的攔截器需要在xml
文件中配置,而Spring Boot
只需要在類上加@Component
注解即可,這樣當前攔截器才會被掃描到。
這里只需要實現HandlerInterceptor
接口即可(這里沒啥坑)。
@Component public class SecurityInterceptor implements HandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(SecurityInterceptor.class); private final ApiSecurityProperties security; @Autowired public SecurityInterceptor(ApiSecurityProperties security) { this.security = security; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url = request.getRequestURI(); if (!url.contains"/api")) { return true; } String secret = request.getHeader("secret"); if (!security.getSecret().equals(secret)) { // 秘鑰不匹配 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); Res<Void> res = ResUtils.error("The argument 'secret' in request headers is error, please check it again."); String result = new Gson().toJson(res); PrintWriter out = response.getWriter(); out.print(result); out.close(); return false; } return true; } }
2.2、將攔截器配置到Spring Boot
環境中
目前(
2.0.4.RELEASE
版本)WebMvcConfigurerAdapter
已過時,如果你執意要用的話,應該沒啥坑。但是被強迫症時刻針對的人,坑就來啦。WebMvcConfigurerAdapter
過時了,那么用誰來代替呢?機智的人可能早就發現了,過時的這個只不過是個適配器(適配器模式),那就可以直接使用它所實現的那個接口啊,就是WebMvcConfigurer
唄。對,就是這個,別猶豫了。。我就被百度坑得不輕,具體說說怎么被坑的吧。
- 百度后我查到的解決方案這樣的
兩種方法,並且都還強烈推薦第二種方法
// 方法一:實現WebMvcConfigurer接口 public class WebConfig implements WebMvcConfigurer{ // ... } // 方法二:繼承WebMvcConfigurationSupport類 public class WebConfig extends WebMvcConfigurationSupport{ // ... }
於是就直接用了第二種方法,寫完跑了項目發現沒啥效果,打日志也出不來。然后又改回第一種方法,果然,有效果了。
具體配置如下
必須加上@Configuration
注解,這樣里邊的@Bean
才能起作用,Spring
才能統一管理當前的攔截器實例。addPathPatterns("/api/**")
配置攔截路徑,其中/**
表示當前目錄以及所有子目錄(遞歸),/*
表示當前目錄,不包括子目錄。
@Configuration public class WebMvcConfig implements WebMvcConfigurer { private final ApiSecurityProperties security; @Autowired public WebMvcConfig(ApiSecurityProperties security) { this.security = security; } @Bean public SecurityInterceptor securityInterceptor() { return new SecurityInterceptor(security); } @Override public void addInterceptors(InterceptorRegistry registry) { // 添加攔截器 registry.addInterceptor(securityInterceptor()).addPathPatterns("/api/**"); } }
不出意外的話,你的攔截器應該起作用啦!