问题描述
我们一般在拦截器中会写一些逻辑处理,比如获取用户的登录信息,将信息存入ThreadLocal等等。
而获取用户信息的时候就有多种方式了。
比如:在session中获取,或者使用token去redis中获取。
这个问题就是使用token去redis中获取用户信息的时候遇到的。因为在获取时需要使用@Autowired将StringRedisTemplate注入。此时运行就遇到了空指针错误。
原因分析
原因:因为拦截器在其配置类里是使用new创建的,而使用new创建的类就不归spring管理了,所以在里面使用@Autowired也将报错。
配置类代码如下:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomerInterceptor()).addPathPatterns("/customer/**");
registry.addInterceptor(new ManageInterceptor()).addPathPatterns("/manage/**");
}
}
解决方案:
方案一:
将拦截器类中添加@Component注解,然后在WebMvcConfigure类中使用@Autowird,将拦截器对象注入进来
代码如下:
@Component
public class CustomerInterceptor extends HandlerInterceptorAdapter {
@Autowired
private StringRedisTemplate stringRedisTemplate ;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("accessToken");
if (token == null){
PrintWriter out = response.getWriter();
out.print(JSON.toJSON(ResultUtil.error("请进行登录")));
return false;
}
if (TokenUtils.verify(token)){
JSONObject object = JSONObject.fromObject(stringRedisTemplate.opsForValue().get(token));
CustomerVo msg = (CustomerVo)JSONObject.toBean(object, CustomerVo.class);
CustomerThreadLocal.set(msg);
if (msg!=null){
return true;
}
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
CustomerInterceptor customerInterceptor;
@Autowired
ManageInterceptor manageInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customerInterceptor).addPathPatterns("/customer/**");
registry.addInterceptor(manageInterceptor).addPathPatterns("/manage/**");
}
}
方案二:
无需在拦截器类上添加@Component直接,直接在WebMvcConfigure类中添加经由@Bean注解的返回拦截器对象的方法。
代码:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public CustomerInterceptor customerInterceptor(){
return new CustomerInterceptor();
}
@Bean
public ManageInterceptor manageInterceptor(){
return new ManageInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customerInterceptor()).addPathPatterns("/customer/**");
registry.addInterceptor(manageInterceptor()).addPathPatterns("/manage/**");
}
}