系列博客目录
文章目录
1.为什么我可以在拦截其中BaseContext.setCurrentId(empId);然后在controller中通过BaseContext.getCurrentId(empId);拿到值。
你能够在拦截器中调用 BaseContext.setCurrentId(empId)
,并在控制器中通过 BaseContext.getCurrentId()
拿到值,是因为 ThreadLocal
的作用。ThreadLocal
可以让你在同一个线程内跨方法传递数据,而这些数据是线程独立的。
主要原因是 ThreadLocal
如何工作
1. ThreadLocal
是基于线程的
ThreadLocal
会为每个线程维护一份独立的变量副本。当你在拦截器中调用 BaseContext.setCurrentId(empId)
时,数据会存储在当前请求的线程的 ThreadLocal
存储中。同一请求线程中后续所有的方法调用都可以访问到这份存储。
- 在拦截器中调用
BaseContext.setCurrentId(empId)
,将empId
设置到当前线程的ThreadLocal
存储中。 - 在控制器中调用
BaseContext.getCurrentId()
,可以从当前线程的ThreadLocal
中获取先前存储的数据(即empId
)。
2. 请求线程的独立性
当 Web 应用处理一个 HTTP 请求时,通常每个请求都会在一个独立的线程中执行。因此,所有在同一线程内执行的操作(例如拦截器和控制器中的方法)都可以共享同一个 ThreadLocal
变量的数据。
- 在拦截器中设置
BaseContext.setCurrentId(empId)
时,empId
会被保存在当前请求所使用的线程中的ThreadLocal
变量里。 - 当请求到达控制器时,同一线程仍然在执行,所以控制器可以通过
BaseContext.getCurrentId()
获取到相同的empId
。
工作过程:
-
拦截器阶段:
- 在请求的拦截器中,你调用了
BaseContext.setCurrentId(empId)
,此时empId
被保存在当前请求线程的ThreadLocal
存储中。
public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Long empId = getEmpIdFromRequest(request); BaseContext.setCurrentId(empId); // 将 empId 设置到当前线程的 ThreadLocal 中 return true; } }
- 在请求的拦截器中,你调用了
-
控制器阶段:
- 在控制器中,通过
BaseContext.getCurrentId()
获取当前线程的ThreadLocal
中的empId
,因为该线程中存储了拦截器中设置的数据。
@RestController public class MyController { @GetMapping(
- 在控制器中,通过