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

远程调用丢失请求头问题

  1. 远程调用,首先执行 this.dispatch.get(method)).invoke(args) 方法
    public class ReflectiveFeign extends Feign 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (!"equals".equals(method.getName())) {
                if ("hashCode".equals(method.getName())) {
                    return this.hashCode();
                } else {
                    return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
                }
            } else {
                try {
                    Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                    return this.equals(otherHandler);
                } catch (IllegalArgumentException var5) {
                    return false;
                }
            }
        }
    }
    
  2. 单步跟踪调试,会到达 SynchronousMethodHandler 类的 invoke 方法
    final class SynchronousMethodHandler implements MethodHandler {
    
        public Object invoke(Object[] argv) throws Throwable {
            RequestTemplate template = this.buildTemplateFromArgs.create(argv);
            Options options = this.findOptions(argv);
            Retryer retryer = this.retryer.clone();
    
            while(true) {
                try {
                    return this.executeAndDecode(template, options);
                } catch (RetryableException var9) {
                    RetryableException e = var9;
    
                    try {
                        retryer.continueOrPropagate(e);
                    } catch (RetryableException var8) {
                        Throwable cause = var8.getCause();
                        if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {
                            throw cause;
                        }
    
                        throw var8;
                    }
    
                    if (this.logLevel != Level.NONE) {
                        this.logger.logRetry(this.metadata.configKey(), this.logLevel);
                    }
                }
            }
        }
        
        Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
            Request request = this.targetRequest(template);
            if (this.logLevel != Level.NONE) {
                this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
            }
    
            long start = System.nanoTime();
    
            Response response;
            try {
                response = this.client.execute(request, options);
                response = response.toBuilder().request(request).requestTemplate(template).build();
            } catch (IOException var13) {
                if (this.logLevel != Level.NONE) {
                    this.logger.logIOException(this.metadata.configKey(), this.logLevel, var13, this.elapsedTime(start));
                }
    
                throw FeignException.errorExecuting(request, var13);
            }
    
            long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
            if (this.decoder != null) {
                return this.decoder.decode(response, this.metadata.returnType());
            } else {
                CompletableFuture<Object> resultFuture = new CompletableFuture();
                this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime);
    
                try {
                    if (!resultFuture.isDone()) {
                        throw new IllegalStateException("Response handling not done");
                    } else {
                        return resultFuture.join();
                    }
                } catch (CompletionException var12) {
                    Throwable cause = var12.getCause();
                    if (cause != null) {
                        throw cause;
                    } else {
                        throw var12;
                    }
                }
            }
        }
    }
    
    this.targetRequest 方法,会构造一个http请求,而该方法的功能是应用各种拦截器,增强 RequestTemplate 对象,最终返回request对象,如下:
        Request targetRequest(RequestTemplate template) {
            Iterator var2 = this.requestInterceptors.iterator();
    
            while(var2.hasNext()) {
                RequestInterceptor interceptor = (RequestInterceptor)var2.next();
                interceptor.apply(template);
            }
    
            return this.target.apply(template);
        }
    
    在这里插入图片描述
    断点调试后,发现header是空的。究其原因,是容器中没有任何拦截器用来构造request请求,因此,request 对象 headers变量的值为空。
    流程如下:
    在这里插入图片描述

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

在这里插入图片描述
向 Spring 容器中放入自定义拦截器,解决feign远程调用丢失请求头问题。

@Configuration
public class FeignConfig {

    @Bean
    public RequestInterceptor requestInterceptor() {

        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                System.out.println("feign远程调用之前,先运行RequestInterceptor.apply()方法");
                // 1. RequestContext 拿到刚进来的这个请求
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                // 同步请求头数据 Cookie
                String cookie = request.getHeader("Cookie");
                // 给新请求同步老请求的Cookie
                requestTemplate.header("Cookie", cookie);
            }
        };
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值