多线程环境:
在多线程环境下,每个线程都有自己的请求上下文。当一个线程处理请求时,它会将请求相关的数据存储在ThreadLocal
中。然而,当这个线程处理完请求后,它会释放这些数据,以便其他线程可以使用ThreadLocal
来存储自己的请求数据。
RequestContextHolder:
在多线程环境下,当一个线程处理完请求后,它会释放ThreadLocal
中的请求数据。这意味着,当另一个线程处理请求时,它不会访问到前一个线程的请求数据,包括请求头。因此,即使使用了RequestInterceptor
,多线程下还是会丢失header头。
Controller和Service是否在同一线程:
在多线程环境下,控制器(Controller)和服务(Service)可能不在同一个线程中。当控制器处理请求时,它会将请求相关的数据存储在ThreadLocal
中。然而,当控制器调用服务来处理业务逻辑时,这个请求数据可能会被释放,以便其他线程可以使用ThreadLocal
来存储自己的请求数据。因此,即使服务在同一个线程中,它也可能无法访问到控制器的请求数据,包括请求头。
通过以上分析,单线程下生效的原理在于请求的处理是顺序的,RequestInterceptor
能够正确地获取到请求头,并将其添加到新的请求中。而多线程下Interceptor不生效的原因在于ThreadLocal
的作用域和多线程环境,以及控制器和服务可能不在同一个线程中。
在创建线程的之前把ThreadLocal中内容取出,然后设置到子线程的ThreadLocal中。
创建一个抽象类,实现Runnable
方法。
public abstract class MyRunnable implements Runnable{
private RequestAttributes requestAttributes;
public MyRunnable() {
requestAttributes = RequestContextHolder.getRequestAttributes();
}
public abstract void myRun();
@Override
public void run() {
//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);
myRun();
}
}
用法如下:
//开启第一个异步任务
CompletableFuture<Void> addressFuture2 = CompletableFuture.runAsync(new MyRunnable() {
@Override
public void myRun() {
//1、远程查询所有的收获地址列表
List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
confirmVo.setMemberAddressVos(address);
}
}, threadPoolExecutor);
因篇幅问题不能全部显示,请点此查看更多更全内容