Feign远程调用丢失请求头问题

Feign远程调用丢失请求头问题

1.debug Feign远程
在这里插入图片描述
2.
在这里插入图片描述
3.远程调用实际是new 了一个新的RequestTemplate,并没有把之前请求的header给设置进去
在这里插入图片描述
4.
在这里插入图片描述
5.可以通过拦截器,拦截请求,然后在给请求设置上,原请求的header信息即可
在这里插入图片描述

图解:
在这里插入图片描述

解决:

@Configuration
public class FeignConfig {

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                //1.RequestContextHolder拿到当前请求的数据,相当与拿到controller入参的HttpServletRequest
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                //老请求
                HttpServletRequest request = requestAttributes.getRequest();

                //2.同步请求头信息->cookie
                String cookie = request.getHeader("Cookie");
                requestTemplate.header("Cookie",cookie);
            }
        };
    }
}

在这里插入图片描述

Feign异步调用丢失请求头问题

还是上面的服务,只是改成异步调用

    @Override
    public OrderConfirmVo confirmOrder() {
        OrderConfirmVo orderConfirmVo=new OrderConfirmVo();
        //当前登录的用户
        MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get();

        //1.异步任务1 - 远程查询所有的收货地址列表
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
            orderConfirmVo.setMemberAddressVos(address);
        }, threadPoolExecutor);


        //2.异步任务2 - 远程查询购物车所有选中的购物项
        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
            List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems();
            orderConfirmVo.setItems(currentCartItems);
        }, threadPoolExecutor);
        //feign在远程调用之前要构造请求,调用很多的拦截器

        try {
            //等待所有任务完成
            CompletableFuture.allOf(voidCompletableFuture,voidCompletableFuture1).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        //3.查询用户积分
        Integer integration = memberResponseVo.getIntegration();
        orderConfirmVo.setIntegration(integration);

        //4.其他数据自动计算

        return orderConfirmVo;
    }

改为了异步,发现之前的FeignConfig配置类在获取ServletRequestAttributes时,获取不到了
在这里插入图片描述
原因:旧请求是在线程A上,当使用异步时,是新开了一条线程去执行,新开的线程自然没有线程A的各种属性以及数据

图解:
在这里插入图片描述

解决:将旧线程中的属性RequestAttributes,设置到新线程中即可

    @Override
    public OrderConfirmVo confirmOrder() {
        OrderConfirmVo orderConfirmVo=new OrderConfirmVo();
        //当前登录的用户
        MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get();
		
		//解决:--------------------------------------
        //获取旧线程的RequestAttributes
        //RequestContextHolder底层使用的是ThreadLocal
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        //1.异步任务1 - 远程查询所有的收货地址列表
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
        	//解决:--------------------------------------
            //将旧线程中的RequestAttributes,设置到线程中的RequestContextHolder里
            RequestContextHolder.setRequestAttributes(requestAttributes);


            List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
            orderConfirmVo.setMemberAddressVos(address);
        }, threadPoolExecutor);


        //2.异步任务2 - 远程查询购物车所有选中的购物项
        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
        	//解决:--------------------------------------
            //将旧线程中的RequestAttributes,设置到线程中的RequestContextHolder里
            RequestContextHolder.setRequestAttributes(requestAttributes);

            List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems();
            orderConfirmVo.setItems(currentCartItems);
        }, threadPoolExecutor);
        //feign在远程调用之前要构造请求,调用很多的拦截器

        try {
            //等待所有任务完成
            CompletableFuture.allOf(voidCompletableFuture,voidCompletableFuture1).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        //3.查询用户积分
        Integer integration = memberResponseVo.getIntegration();
        orderConfirmVo.setIntegration(integration);

        //4.其他数据自动计算

        return orderConfirmVo;
    }

配置类加个非空判断即可

@Configuration
public class FeignConfig {
    @Bean
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                //1.RequestContextHolder拿到当前请求的数据,相当与拿到controller入参的HttpServletRequest
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

                if (requestAttributes!=null){
                    //老请求
                    HttpServletRequest request = requestAttributes.getRequest();

                    if (request!=null){
                        //2.同步请求头信息->cookie
                        String cookie = request.getHeader("Cookie");
                        requestTemplate.header("Cookie",cookie);
                    }
                }
            }
        };
    }
}

再次测试:
在这里插入图片描述
ok,解决

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值