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

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

使用Feign远程调用默认不会携带请求头

如果把一些登录的信息放在Cookie中,再使用Feign远程调用时,默认情况下生产者处理的业务,会因为不能从请求头中获取登录状态而返回错误的结果

如果生产者需要请求头,则要向容器中添加请求拦截器(feign构造时会使用容器中的请求拦截器来构造,如果没有就用默认的)

Feign远程调用丢失请求头问题_第1张图片

@Configuration
public class GulimallFeignConfig {

    //请求拦截器 解决Feign远程调用没有请求头问题
    @Bean("requestInterceptor")
    public RequestInterceptor requestInterceptor() {
        return new RequestInterceptor() {
            /**
             * @param template 新请求
             */
            @Override
            public void apply(RequestTemplate template) {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                //如果使用异步Feign远程调用时,且不在异步执行的线程上设置主线程的请求头 ServletRequestAttributes会为空 
                if (attributes!=null) {
                    //拿到老请求
                    HttpServletRequest request = attributes.getRequest();
                    //将老请求 请求头中的cookie添加到模板上,拦截器会使用模板构建新请求
                    String cookie = request.getHeader("Cookie");
                    template.header("Cookie", cookie);
                }
            }
        };
    }
}

分析使用Feign时的源码可以发现:最终构建请求时会遍历请求拦截器来构建请求(因此我们添加进容器的请求拦截器也会用来构建请求,所以请求会带上我们设置的请求头)

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

如果异步使用Feign远程调用,则实际执行远程调用的线程不会原来的主线程了

所以异步执行远程调用的线程,在请求拦截器中可能取不出请求头

Feign远程调用丢失请求头问题_第2张图片

这种情况需要在异步执行的线程中先设置好与主线程相同的请求上下文ServletRequestAttributes

		ServletRequestAttributes attributes = (ServletRequestAttributes) 	
        RequestContextHolder.getRequestAttributes();

        //查询地址列表
        CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
            //异步远程调用 先将主线程的ServletRequestAttributes
            RequestContextHolder.setRequestAttributes(attributes);
            List<MemberAddressVo> address = memberFeignService.getAddress(member.getId());
            orderConfirmVo.setAddress(address);
        }, executor);

你可能感兴趣的:(项目,Feign,java)