一、问题重现


楼主在使用feign进行声明式服务调用的时候发现,当GET请求为多参数时,为方便改用DTO对象进行参数传递。但是,在接口调用时feign会抛出一个405的请求方式错误:

{"timestamp":1540713334390,"status":405,"error":"Method Not Allowed", "exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/role/get"}

API接口层代码如下:

@RequestMapping(value = "/role")
public interface RoleService {
@GetMapping(value = "/get")
Result<RuleInfoVO> getRoleInfo(RoleInfoRequest request); }

服务端实现:

@Slf4j
@RestController
public class RoleInfoResource implements RoleService { @Override
public Result<RuleInfoVO> getRoleInfo(RoleInfoRequest request) {
log.info("params of getRoleInfo:{}",request);
return new Result<>();
}
}

feign客户端调用:

@Slf4j
@RestController
@RequestMapping(value = "/role")
public class RoleController { @Autowired
private RoleInfoApi roleInfoApi; @GetMapping(value = "/get")
public Result<RuleInfoVO> getRuleInfo(RoleInfoRequest request){
log.info("params of getRuleInfo:{}",request);
Result<RuleInfoVO> result = this.roleInfoApi.getRoleInfo(request);
log.info("result of getRuleInfo:{}",result);
return result;
}
}

检查feign调用方式与服务端所声明的方式一致,但是为什么为抛出405异常?带着该疑问稍微跟了一下源码,发现feign默认的远程调用使用的是jdk底层的HttpURLConnection,这在feign-core包下的Client接口中的convertAndSend方法可看到:

if (request.body() != null) {
if (contentLength != null) {
connection.setFixedLengthStreamingMode(contentLength);
} else {
connection.setChunkedStreamingMode(8196);
}
connection.setDoOutput(true);
OutputStream out = connection.getOutputStream();
if (gzipEncodedRequest) {
out = new GZIPOutputStream(out);
} else if (deflateEncodedRequest) {
out = new DeflaterOutputStream(out);
}
try {
out.write(request.body());
} finally {
try {
out.close();
} catch (IOException suppressed) { // NOPMD
}
}
}

该段代码片段会判断requestBody是否为空,我们知道GET请求默认是不会有requestBody的,因此该段代码会执行到HttpURLConnection中的 private synchronized OutputStream getOutputStream0() throws IOException; 方法:

 if (this.method.equals("GET")) {
this.method = "POST";
}

最关键的代码片段已显示当请求方式为GET请求,会将该GET请求修改为POST请求,这也就是4返回05状态的根本原因。

二、解决方案


幸运的是,feign为我们提供了相应的配置解决方案。我们只需将feign底层的远程调用由HttpURLConnection修改为其他远程调用方式即可。而且基本不需要修改太多的代码,只需再依赖中加入feign-httpclient包的依赖,并在@RequestMapping注解中加入consumes的属性即可:

 compile 'io.github.openfeign:feign-httpclient:9.5.1'

楼主用的gradle,使用maven的大佬请自行更改为maven的配置方式。

增加@GetMapping注解的consumes属性,使用@RequestMapping的大佬也一样:

 @RequestMapping(value = "/role")
public interface RoleService { @GetMapping(value = "/get",consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
Result<RuleInfoVO> getRoleInfo(@RequestBody RoleInfoRequest request); }

大功告成:

源代码请各位大佬移步:https://github.com/LJunChina/cloud-solution-staging

spring cloud——feign为GET请求时的对象参数传递的更多相关文章

  1. 使用Spring Cloud Feign 日志查看请求响应

    在使用微服务时,常常会用feign做客户端去调用别的微服务,但是在日志中很难查看到具体的请求和响应.因此,需要把feign默认的日志打开. 日志设置 创建feign配置类 @Configuration ...

  2. 笔记:Spring Cloud Feign 其他配置

    请求压缩 Spring Cloud Feign 支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗,我们只需要通过下面二个参数设置,就能开启请求与响应的压缩功能,yml配置格式如下: fei ...

  3. 第六章:声明式服务调用:Spring Cloud Feign

    Spring Cloud Feign 是基于 Netflix Feign 实现的,整合了 Spring Cloud Ribbon 和 Spring Cloud Hystrix,除了提供这两者的强大功能 ...

  4. spring cloud feign不支持@RequestBody+ RequestMethod.GET,报错

    1.问题梳理: 异常:org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not ...

  5. 笔记:Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  6. 笔记:Spring Cloud Feign 声明式服务调用

    在实际开发中,对于服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以我们通常会针对各个微服务自行封装一些客户端类来包装这些依赖服务的调用,Spring Cloud Feign 在此基础上做了进 ...

  7. Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  8. RestTemplate OR Spring Cloud Feign 上传文件

    SpringBoot,通过RestTemplate 或者 Spring Cloud Feign,上传文件(支持多文件上传),服务端接口是MultipartFile接收. 将文件的字节流,放入ByteA ...

  9. 第六章 声明式服务调用: Spring Cloud Feign

    我们在使用 Spring Cloud Ribbon 时, 通常都会利用它对 RestTemplate 的请求拦截来实现对依赖服务的接口调用, 而 RestTemplate 已经实现了对 HTTP 请求 ...

随机推荐

  1. saltstack自动化运维系列⑥SaltStack实践安装配置HAproxy的Keepalived

    saltstack自动化运维系列⑥SaltStack实践安装配置HAproxy的Keepalived 安装配置Keepalived 1.编写功能模块 #创建keepalived目录# mkdir -p ...

  2. Go语言规格说明书 之 结构体类型(Struct types)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  3. transfer pdf to png

    #! /bin/bash # # transfer pdf to png if [ $# != 1 ] ; then echo "USAGE: $0 PDF FILE ABSOLUTELY ...

  4. js几种创建对象的方式

    javascript是一种“基于prototype的面向对象语言“,与java有非常大的区别,无法通过类来创建对象.那么,既然是面象对象的,如何来创建对象呢? 一.通过”字面量“方式创建. 方法:将成 ...

  5. STM32应用实例八:与多台MS5803压力传感器I2C通讯

    MS5803压力传感器支持SPI和I2C总线通讯,拥有24位AD转换.能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度.各引脚功能及参数如下: ...

  6. php数组去重(一维数组)

    <?php $arr = ['1', '1', 'PHP', 'PHP', 2, 3]; print_r($arr); echo "<br>"; print_r( ...

  7. hdu 1575 求一个矩阵的k次幂 再求迹 (矩阵快速幂模板题)

    Problem DescriptionA为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input数据的第一行是一个T,表示有T组数据.每组数据的第一行有 ...

  8. SpringBatch 错误积累

    1.如果nextStep在该JOB中还没有配置,也就是说nextStep还不存在的情况下,就会报错 <end on="EIXT WITH IMBALANCE" /> & ...

  9. [SDOI2012]拯救小云公主

    题解: 是一个不错的题目 首先我们可以考虑二分答案 然后变成判定性问题 对于每个画一个圆 当其会被阻断时就是答案 阻断有四种情况 左下 上下 左右 右上 但是这样是n^2a(n)*logn的 考虑直接 ...

  10. jenkins X实践系列(2) —— 基于jx的DevOps实践

    jx是云原生CICD,devops的一个最佳实践之一,目前在快速的发展成熟中.最近调研了JX,这里为第2篇,使用已经安装好的jx来实践CICD,旨在让大家了解基于jx的DevOps是如何运转的,感兴趣 ...