因为ThreadLocal是一种并发机制,它确保每个线程都有自己独立的变量副本,从而避免了线程间的共享和同步问题,所以可以使用ThreadLocal保存当前登录用户的信息,方便进行鉴权等操作
- 定义好RequestHolder,用于操作保存信息
public class RequestHolder {
public static final String TOKEN = "token";
public static final String USER_INFO = "user_info";
private static ThreadLocal<Map<String, Object>> LOCAL = new TransmittableThreadLocal<Map<String, Object>>() {
protected synchronized Map<String, Object> initialValue() {
return new WeakHashMap<>();
}
};
public static Object getValue(String key) {
return LOCAL.get().get(key);
}
public static void setValue(String key, Object value) {
LOCAL.get().put(key, value);
}
public static String getToken(){
Object value = getValue(TOKEN);
if(value==null){
return null;
}
return (String) value;
}
public static UserInfo getUser(){
Object o = getValue(RequestHolder.USER_INFO);
if(o==null){
return null;
}
UserInfo userDTO = (UserInfo) o;
return userDTO;
}
public static Long getUserId(){
UserInfo user = getUser();
if( user == null )
return null;
return getUser().getId();
}
public static void invalidator(){
LOCAL.remove();
}
}
- 可以在拦截器中对传入的用户id等参数进行处理,获取到用户信息再进行保存
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 优先从请求头获取token
String token = request.getHeader(RequestHolder.TOKEN);
// 获取用户信息
User user = getUserInfoByToken(token);
RequestHolder.setValue(RequestHolder.USER_INFO, user);
...其他处理逻辑
}
}
- 这样就可以在处理业务的时候,直接通过
- RequestHolder.getUser().getUserName()就可以拿到当前用户的相关信息