前言
最近在优化代码,将部分码帮帮代码重写了一下,然后就发现了Open Feign 发送GET请求入参为@RequestBody时调用失败的问题!
问题重现
controller层
fegin层
这里可能有人对controller层有疑问,不是说GET只支持@PathVariable(URL入参),@RequestParam(Params入参),这里其实只是常见的,我只能说这是常规规范而已,具体的细节请看往期文章前后端分离项目VUE使用axios调用微服务SpringBoot后端接口无法获取参数,这篇文章中有详细说明前后端各种入参、传递、解析规则!
调用测试
这里我调用发现,调用是失败的,异常信息是不支持请求方法’POST’,但是我这里明明使用的是@GetMapping("/basic/data/getSysDictDataByIds")方式,只不过携带的参数是@RequestBody!很迷!
原因分析
深入源码
HttpClientFeignConfiguration
这个类在不存在ILoadBalancer时才触发,我们项目开启了Ribbon,所以肯定存在,再看注释:载入负载均衡ribbon clients需要走FeignRibbonClientAutoConfiguration这个类配置
进入FeignRibbonClientAutoConfiguration源码
看红框注释:按照导入从上往下的序:HttpClientFeignLoadBalancedConfiguration>OkHttpFeignLoadBalancedConfiguration>DefaultFeignLoadBalancedConfiguration,对应的底层http工具:httpclient>okhttp>HttpURLConnection
根据http协议定义是支持@RequestBody+ RequestMethod.GET的,那么具体就得看工具包实现的不同的,查看源码发现okhttp和HttpURLConnection都不支持(报错),只有httpclient支持。(默认走HttpURLConnection会报错)
httpclient支持@RequestBody+ RequestMethod.GET
只有httpclient支持@RequestBody+ RequestMethod.GET,所以我们必须满足条件走HttpClientFeignLoadBalancedConfiguration才行,看下源码:
先决条件ApacheHttpClient.class类存在时!这就涉及到HTTP协议的问题了,这里采用的是Apache HTTP的协议。
解决方案
导入feign-httpclient依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
补充
URLConnection
报405错误,说明http方法不对,但是feign配置是GET方法,查feign的日志也是用的GET方法。后来发现原因是URLConnection在的原因:对于有request body的GET方法,自动改为POST方法了。
OkHttp
直接报错:method GET must not have a request body.
ApacheHttpClient
完美支持。