解决方案
基于ThreadLocal + 拦截器的形式统一处理
package com.tanhua.server.interceptor;import com.tanhua.commons.utils.JwtUtils;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class TokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取请求头中的tokenString token = request.getHeader("Authorization");//2.校验token合法性boolean verifyToken = JwtUtils.verifyToken(token);if(!verifyToken){//token失效,拦截response.setStatus(401);return false;}//3.放行return true;}
}
package com.tanhua.server.config;import com.tanhua.server.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**")//拦截所有请求.excludePathPatterns(new String[]{"/user/login",//获取验证码和登录不需要拦截,没有登录没有token"/user/loginVerification"//});}
}
接着就可以删除掉Controller中的token校验的代码了
ThreadLocal的存储类,可以使线程有存储数据的能力,
线程内调用的方法都可以从ThreadLocal中获取同一个对象。
多个线程中ThreadLocal数据相互隔离
package com.tanhua.server.interceptor;import com.tanhua.model.domain.User;public class ThreadLocalUntils {private static ThreadLocal tl =new ThreadLocal<>();//向ThreadLoad存储用户对象public static void setUser(User user){tl.set(user);}//在Threadlocal中获取用户对象public static User getUser(){User user = tl.get();return user;}//在Threadlocal中获取用户对象的idpublic static Long getUserId(){User user = tl.get();Long id = user.getId();return id;}//在Threadlocal中获取用户对象的手机号码public static String getUserPhone(){User user = tl.get();String mobile = user.getMobile();return mobile;}
}
package com.tanhua.server.interceptor;import com.tanhua.commons.utils.JwtUtils;
import com.tanhua.model.domain.User;
import io.jsonwebtoken.Claims;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;//定义拦截器
public class TokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取请求头tokenString token = request.getHeader("Authorization");//2.校验token合法性boolean verifyToken = JwtUtils.verifyToken(token);if(!verifyToken){//token为空或失效response.setStatus(401);return false;}//3.token正常,获取token携带的用户id和手机号码构造用户存进threadlocalClaims claims = JwtUtils.getClaims(token);Integer id = (Integer) claims.get("id");String phone = (String) claims.get("phone");User user =new User();user.setId(Long.valueOf(id));user.setMobile(phone);ThreadLocalUtils.set(user);return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {ThreadLocalUtils.remove();}
}
ion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
ThreadLocalUtils.remove();
}
}
其他的controller中可以删除token中校验token和解析token的代码,用ThreadLocalUntils获取用户id