此案例是在springboot的框架上使用,通过ThreadLocal存储用户信息,并通过UserThreadLocal类中的get()方法获取其中的用户信息。
1.编写一个UserThreadLocal类
public class UserThreadLocal {
//声明为私有的
private UserThreadLocal(){}
private static final ThreadLocal<SysUser> LOCAL = new ThreadLocal<>();
//放
public static void put(SysUser sysUser){
LOCAL.set(sysUser);
}
//取
public static SysUser get(){
return LOCAL.get();
}
//删除
public static void remove(){
LOCAL.remove();
}
}
在此类中新建一个私有唯一的静态ThreadLocal对象LOCAL。还有用于将用户信息存放在ThreadLocal中的put方法,和从ThreadLocal中获取用户信息的get方法,以及删除ThreadLocal的remove方法。
最后还有一个用户信息实体类SysUser。
2.在其他类中使用UserThreadLocal.put(sysUser)存放用户信息
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private LoginService loginService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//在执行controller方法(Handler)之前进行执行
/**
* 1.需要判断请求的接口路径是否为 HandlerMethod (controller方法)
* 2.判断token是否为空,如果为空未登录
* 3.如果token不为空,登录验证loginservice checkToken
* 4.如果认证成功放行即可
*/
if (!(handler instanceof HandlerMethod)){
//如果是handler方法,就放行。
return true;
}
//使用slf4j做日志输出
String token = request.getHeader("Authorization");
log.info("=================request start===========================");
String requestURI = request.getRequestURI();
log.info("request uri:{}",requestURI);
log.info("request method:{}",request.getMethod());
log.info("token:{}", token);
log.info("=================request end===========================");
//如果token为空,不放行并提示未登录
if (StringUtils.isBlank(token)){
Result result = Result.fail(ErrorCode.NO_LOGIN.getCode(), "未登录");
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(JSON.toJSONString(result));
return false;
}
//将token解析为sysUser实体类,如果实体类为空,提示不登录,并不放行。
SysUser sysUser = loginService.checkToken(token);
if (sysUser == null){
Result result = Result.fail(ErrorCode.NO_LOGIN.getCode(), "未登录");
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(JSON.toJSONString(result));
return false;
}
//登录验证成功 放行
// 在controller中直接获取用户的信息
UserThreadLocal.put(sysUser);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//如果不删除ThreadLocal中用完的信息会有内存泄漏的风险
UserThreadLocal.remove();
}
}
在我的案例中,我在登录时会经过拦截器拦截进行验证,在登录验证成功后使用UserThreadLocal类中的put方法即UserThreadLocal.put(sysUser),将sysUser用户信息存入ThreadLocal。
特别注意
要使用remove方法删除ThreadLocal中用完的信息,否则会有内存泄漏的风险。本次我是
在LoginInterceptor类中重写afterCompletion方法,即方法执行完毕以后,使用UserThreadLocal.remove删除,防止内存泄漏。