OpenFein的get请求无参数变post详解
2026/5/16 14:07:04 网站建设 项目流程

今天向外域提供fein接口,get请求忘记写入@requesParam注解导致,fein直接变成了post请求,引发了我的好奇,为什么Spring mvc可以,他不可以昵,让我们从源码开始吧,顺便解析完整的fein请求链路:

先给完整链路

Feign 请求完整链路: 1. ReflectiveFeign.FeignInvocationHandler.invoke() → 代理方法入口,确定请求的类及参数 2. SynchronousMethodHandler.invoke() → 通过 buildTemplateFromArgs.create(argv) 组装 RequestTemplate 3. feign.Contract.BaseContract.parseAndValidateMetadata() → 🔑 关键分叉点:判断参数是 param 还是 body → 未加 @RequestParam 的参数被识别为 body 参数 4. ReflectiveFeign.BuildFormEncodedTemplateFromArgs.resolve() → 未加注解走此路径 → encoder.encode() 将参数写入 body → 加了注解走 RequestTemplate.resolve() → 参数拼入 URL query 5. FeignBlockingLoadBalancerClient.execute() → 组装最终 URL,选择负载均衡客户端 6. JDK HttpURLConnection → 执行 connection.getOutputStream() 时 → 🐛 JDK 内部惰性初始化机制强制将 Method 改写为 POST

1、走入fein-core的

1)ReflectiveFeign.FeignInvocationHandler.invoke的代理方法,确定请求的类及参数等,

直到进入选择对应的负载均衡客户端,我这边的默认是第二个

org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient类有buildRequest组装url,然后通过executeWithLoadBalancerLifecycleProcessing进入到
org.springframework.cloud.openfeign.loadbalancer.LoadBalancerUtils的
executeWithLoadBalancerLifecycleProcessing方法中feignClient.execute(feignRequest, options); 重新选择客户端调用,就进入到下面这张图了

是不是发现不对了,哈哈哈哈,回过头,发现是执行了

OutputStream out = connection.getOutputStream();

就会变,刚开始我也没有搞明白,查阅资料说是JDK HttpURLConnection 的内部惰性初始化 + 强制改写 Method导致的,好了找到问题,然后又有疑惑,怎么办尼,那就试试正确的方法,看看是怎么解析的。你会发现他不会走到这里,so,说明了,还有一个地方,在确认request.body()是不是为null的地方,这里也是一个因素

好了正确的,我们又要回到

fein-core的SynchronousMethodHandler组装请求的方法

RequestTemplate template = buildTemplateFromArgs.create(argv);
RequestTemplate template = resolve(argv, mutable, varBuilder);

然后一直走encode方法,就会发现有一个写入body的,但是他需要判断outputMessage!=null,

不为 messageConverter instanceof GenericHttpMessageConverter

会把我们的值,自动判断为body

到这其实差不多就结束了,但是还会有个疑问

对的请求是怎样走的昵,我重新模拟了一下,只有没加注解的会走这个

feign.ReflectiveFeign.BuildFormEncodedTemplateFromArgs.resolve

然后走encoder.encode方法,没加的是不会,所以还能继续往上推,RequestTemplate mutable的resolve如何定义的,

feign.ReflectiveFeign.BuildTemplateByResolvingArgs.resolve

加上了注解就会走

feign.RequestTemplate.resolve

所以现在问题原因已经定位到了,获取这个配置,导致resolve方法不一样

RequestTemplate mutable = RequestTemplate.from(metadata.template());

那RequestTemplate是什么时候生成的昵,上代码

feign.Contract.BaseContract.parseAndValidateMetadata方法

判断是什么参数的地方,param还是body,前面遗留的为什么不加requestParam会走body参数,是不是真相大白了

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询