欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 18:37:19
...

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

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

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

解决:

@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远程调用丢失请求头问题

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时,获取不到了
Feign远程调用丢失请求头问题
原因:旧请求是在线程A上,当使用异步时,是新开了一条线程去执行,新开的线程自然没有线程A的各种属性以及数据

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

解决:将旧线程中的属性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);
                    }
                }
            }
        };
    }
}

再次测试:
Feign远程调用丢失请求头问题
ok,解决

相关标签: SpringCloud