介绍:
ThreadLocal 并不是一个Thread,而是Thread的局部变量。
ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
注意:
拦截器->controller ->service->mapper 属于同一个线程 在拦截器分析token时,就将token信息保存在线程局部变量中。
验证:
在拦截器,Service,和controller层分别获取thread的id,查看是否一样
通过发送新增员工的请求 可以看到输出的当前进程id相同
客户端发起的每次请求都是一个单独的进程,同一个进程里面的数据可以共享
常用方法:
- public void set(T value) 设置当前线程的线程局部变量的值
- public T get() 返回当前线程所对应的线程局部变量的值
- public void remove() 移除当前线程的线程局部变量
创建 ThreadLocal 操作的工具类
维护(修改代码)方便,还可以增加复用性(减少代码量);
即代码的可读性和复用性
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}
在jwt拦截器中获取到当前登录用户的id,并且放入到线程局部变量中。
//2、校验令牌
try {
//.................
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
//获取到员工id
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
/将用户id存储到ThreadLocal
BaseContext.setCurrentId(empId);
//在service层中去获取到员工的id
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());