SpringBoot中拦截器配置
不应该叫springboot拦截器,而是SpringMVC拦截器。主要就是对请求进行拦截,然后进行处理
百度百科对于SpringMVC拦截器的解释
在拦截器的处理中前置(pre)拦截是按顺序进行调用,后置拦截(post)是逆序,究其原因是在springmvc调用过程中pre拦截是顺序调用,然后逆序调用post拦截器。
在我的项目中拦截器是用来做token验证,验证用户是否登录,以及保存验证通过的用户信息在ThreadLocal中,然后在请求完成后清空threadlocal,防止发生内存泄漏,至于为什么发生内存泄漏,以前写过一篇文章此处不在赘述。当然了,拦截器还可能有其他用法,等待我去探究
那么如何在SpringBoot中配置SpringMVC的拦截器呢
首先需要实现HandlerInterceptor,具体如下
@Slf4j
public class JwtVerifyInterceptor implements HandlerInterceptor {
@Autowired
UserService userService;
public static final ThreadLocal<User> USER_INFO_THREAD_LOCAL = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("开始验证用户状态。。。");
Cookie[] cookies = request.getCookies();
if (cookies == null || cookies.length == 0) {
return true;
}
for (Cookie cookie : cookies) {
log.info("验证用户状态中");
if ("token".equals(cookie.getName())) {
String token = cookie.getValue();
DecodedJWT decode = JWT.decode(token);
int uid;
try {
uid = Integer.parseInt(decode.getAudience().get(0));
User userInfo = userService.selectByPrimaryKey(uid);
if (userInfo == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
USER_INFO_THREAD_LOCAL.set(userInfo);
} catch (JWTDecodeException jwtDecodeException) {
log.error("token被篡改");
throw new RuntimeException("token格式不正确");
}
}
}
log.info("当前操作用户信息:" + USER_INFO_THREAD_LOCAL.get().toString());
return USER_INFO_THREAD_LOCAL.get() != null;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("请求返回中,清除threadLocal信息");
USER_INFO_THREAD_LOCAL.remove();
}
}
这样就配置好了一个拦截器,但是并不能生效,因为此时springmvc还不知道我们创建了这个拦截器,而且这里也只定义了拦截器的行为它所做的一些操作。对于拦截器什么时候生效,作用的范围,这里并没有体现。所以还需要一个配置类对我们的拦截器进行配置,具体如下
@Configuration
public class InterceptorsConfig implements WebMvcConfigurer {
@Bean
JwtVerifyInterceptor jwtVerifyInterceptor() {
return new JwtVerifyInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
LinkedList<String> excludePathPatterns = new LinkedList<>();
excludePathPatterns.add("/user/login");
excludePathPatterns.add("/user/register");
registry.addInterceptor(jwtVerifyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(excludePathPatterns);
}
}
这里加了@Configuration注解,表明这是一个配置类,springboot会根据它进行配置
可以看到这里用来一个@bean注解,表示将返回的返回值加入到springioc中,为什么要加入ioc中呢,这是因为在拦截器中我用到了userService查询user的信息,但是一般来说,拦截器是在ioc容器前起作用,这个时候容器中并没有UserService实例,也就无法进行依赖注入了。所以需要提前加入到ioc中。
接着就是具体的配置了,将一些路径不适用拦截器,比如注册登录等不需要用户登录状态下进行操作的的资源
然后就是将拦截器实例通过调用方法的形式加到拦截器配置中,然后指定路径以及前面指定好的不进行拦截的uri
至此,springmvc拦截器 已经配置完毕