這個問題一般是解決
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/**");
}
}
不出意外的話,你的攔截器應該起作用啦!