SpringMVC拦截器失效
站在巨人的肩膀上
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/**");
}
}
不出意外的话,你的拦截器应该起作用啦!