SpringBoot项目中Interceptor拦截器中使用@Autowired注解,运行时会报错空指针
1.问题描述
今天新建一个springboot的demo项目,想在interceptor中更新用户token信息,但是在使用过程中,报错服务类对象为null空指针异常,具体代码如下,userService
对象为空,具体原因是因为拦截器在其配置类自定义WebMvcConfigurer
里是使用new创建的,而使用new创建的类就不归spring管理了,所以在里面使用@Autowired也将报错,配置类代码如下,即 registry.addInterceptor( new PermisssionInterceptor() )
这一段,参数是new一个对象
@Configuration
public class PermissionWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor( new PermisssionInterceptor() )
.addPathPatterns("/**") // 拦截页面
.excludePathPatterns("/user/login", "/user/register"); // 放行
}
}
自定义的Interceptor类如下:
/**
* 拦截需要授权的接口
*/
@Slf4j
public class PermisssionInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 检查用户JWT
String jwt = request.getHeader("access-token");
// 校验并取出私有信息
try {
if ("".equals(jwt) || null == jwt) {
throw new CommException("请您先登录");
}
// token 解码
DecodedJWT dj = JwtUtil.decodeToken(jwt);
// 取出基本用户信息加入请求头
String userId = dj.getClaim("userId").asString();
String userName = dj.getClaim("userName").asString();
// jwt校验合格的,将 jwt 中存的用户信息加入请求头,不合格的,请求头存个空用户
request.setAttribute("jwt-user", userId != null ? new User(Integer.valueOf(userId), userName) : new User());
// 计算当前时间是否超过过期时间的一半,如果是就帮用户续签
Long expTime = dj.getExpiresAt().getTime();
Long iatTime = dj.getIssuedAt().getTime();
Long nowTime = new Date().getTime();
if ((nowTime - iatTime) > (expTime - iatTime) / 2) {
// 生成新的jwt
Map<String, String> payload = new HashMap<>();
payload.put("userId", userId); // 加入一些非敏感的用户信息
payload.put("userName", userName); // 加入一些非敏感的用户信息
String newJwt = JwtUtil.generateToken(payload);
// 加入返回头
response.addHeader("access-token", newJwt);
userService.updateToken(userId, userName, newJwt);
}
return true;
} catch (JWTDecodeException e) {
log.error("token令牌错误");
throw new CommException("token令牌错误");
} catch (TokenExpiredException e) {
log.error("token令牌过期");
throw new CommException("token令牌过期");
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
2.解决办法
解决办法有两种,这里参考大神的博客使用其中一种,即直接在WebMvcConfigure
类中添加经由@Bean注解的返回拦截器对象的方法,修改后的PermissionWebConfig
类如下:
@Configuration
public class PermissionWebConfig implements WebMvcConfigurer {
@Bean
public HandlerInterceptor getPermisssionInterceptor(){
return new PermisssionInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getPermisssionInterceptor())
.addPathPatterns("/**") // 拦截页面
.excludePathPatterns("/user/login", "/user/register"); // 放行
}
}
这样问题就可以解决,感谢网络大神!
@https://blog.csdn.net/wangdawei_/article/details/122008669