问题:
Order服务需要远程调用member服务进而查询所有的地址列表,也需要远程调用cart服务进而查询购物车所有选中的购物项,串行执行远程调用会浪费大量时间,因此我们进行异步编排优化
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
OrderConfirmVo confirmVo = new OrderConfirmVo();
MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
开启异步时获取不到老请求的信息即拦截器中会发生空指针的错误,即老request对象获取不到,是null。
@Configuration
public class GulimallFeignConfig {
原因:
@Configuration
public class GulimallFeignConfig {
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
OrderConfirmVo confirmVo = new OrderConfirmVo();
MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
System.out.println("主线程线程...."+Thread.currentThread().getId());
测试打印线程:

我们给feign的拦截器所拦截的请求加上了请求头,但这个获取请求头的过程是在一个线程执行过程中进行的,但是由于 RequestContextHolder底层使用的是线程共享数据 ThreadLocal<RequestAttributes>,线程共享数据的域是当前线程下,线程之间是不共享的。

解决:
向 RequestContextHolder线程域中放主线程的请求域。
即先在主线程中获取到请求头相关信息(RequestContextHolder.getRequestAttributes();),然后在异步调用的过程中将情求头加到正在执行异步操作的线程中( RequestContextHolder.setRequestAttributes(requestAttributes);),这样请求头就不会丢失。
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
OrderConfirmVo confirmVo = new OrderConfirmVo();
MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
虽然都是同一个 RequestContextHolder类在调用方法,但是 RequestContextHolder在不同线程中的意义是不同的,它仅代表当前线程。
@Configuration
public class GulimallFeignConfig {