1.需求
新增/修改员工时,要录入操作人的id,怎么获取操作人的id呢?
2.思路
登录校验时,可以从JWT令牌中解析出当前登录人的id,将这个id保存起来,如果后面要用的话,能够方便的取到。
3.解决方案
3.1 ThreadLocal
ThreadLocal
中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的,ThreadLocal
为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。
当然,用ThreadLocal需要满足一个条件:某个人登录、新增员工(controller, service层)、修改员工(controller, service层)均属于同一个线程。
- 为什么能满足这个条件呢?
3.2 ThreadLocal封装工具类
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) { //设定当前登录的用户id
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}
工具类,里面包含set,get,remove三个静态方法
3.3 使用
首先,在Interceptor的JWT校验部分,调用setCurrentId,即保存了当前登录人的ID
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
BaseContext.setCurrentId(empId); //记好是谁登录的,通过ThreadLocal记录
return true;//3、通过,放行
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
新增员工时,在service层,获取之前保存的当前登录人ID,并设置为creatUser和updateUser
//设置创建人id和更新人id
//要获取当前登录人的id
Long nowLogUserId = BaseContext.getCurrentId();
employee.setCreateUser(nowLogUserId);
employee.setUpdateUser(nowLogUserId);