ThreadLocal是java中的一个线程变量,即ThreadLocal填充的变量属于当前线程,该变量对其他线程而言是隔离的。
基于这个作用,我们可以利用ThreadLocal去解决如何通过解析JWT令牌获取当前登录用户id的问题 。
新建一个工具类BaseContext,里面创建了一个ThreadLocal的对象,并编写了 setCurrentId(),getCurrentId()以及removeCurrentId()方法。
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令牌解析处,使用工具类的setCurrentId()方法即可将用户的id存储到该线程对象中。
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
//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);
//解析jwt令牌,将当前员工id存储到线程对象中
BaseContext.setCurrentId(empId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
如需使用该用户id,即可在使用处,利用getCurrentId()方法将id获取出来。(如使用该id插入到数据库某些字段中)
//设置为当前登录用户的id
employee.setCreateUser(BaseContext.getCurrentId());
employee.setUpdateUser(BaseContext.getCurrentId());
//调用employeeMapper的insert方法添加员工信息
employeeMapper.insert(employee);