Java - ThreadLocal

Parker

介绍

ThreadLocal 并不是一个Thread,而是Thread的局部变量。
ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

常用方法

  • public void set(T value) 设置当前线程的线程局部变量的值
  • public T get() 返回当前线程所对应的线程局部变量的值
  • public void remove() 移除当前线程的线程局部变量

使用场景

在JavaWeb开发中,将从拦截器中解析到的当前登录用户ID传递给其他方法使用。

代码

封装了 ThreadLocal 操作的工具类:

在sky-common模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.sky.context;

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();
}
}

在拦截器中解析出当前登录员工id,并放入线程局部变量中:

在sky-server模块中,拦截器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.sky.interceptor;

/**
* jwt令牌校验的拦截器
*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

@Autowired
private JwtProperties jwtProperties;

/**
* 校验jwt
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

//.............................

//2、校验令牌
try {
//.................
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
log.info("当前员工id:", empId);
/////将用户id存储到ThreadLocal////////
BaseContext.setCurrentId(empId);
////////////////////////////////////
//3、通过,放行
return true;
} catch (Exception ex) {
//......................
}
}
}

在Service中获取线程局部变量中的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 新增员工
*
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
//.............................

//设置当前记录创建人id和修改人id
Long currentId = BaseContext.getCurrentId();
employee.setCreateUser(currentId);
employee.setUpdateUser(currentId);

employeeMapper.insert(employee);
}
评论
此页目录
Java - ThreadLocal