带有 List 参数的 Spring Cloud Feign Client @RequestParam 创建错误的请求

Posted

技术标签:

【中文标题】带有 List 参数的 Spring Cloud Feign Client @RequestParam 创建错误的请求【英文标题】:Spring Cloud Feign Client @RequestParam with List parameter creates a wrong request 【发布时间】:2017-06-04 07:32:52 【问题描述】:

我有一个 Spring Clound Feign Client 映射定义如下

@RequestMapping(method = RequestMethod.GET, value = "/search/findByIdIn")
Resources<MyClass> get(@RequestParam("ids") List<Long> ids);

当我打电话时

feignClient.get(Arrays.asList(1L,2L,3L))

根据我在调试器中看到的,feign-core 库形成以下请求:

/search/findByIdIn?ids=1&ids=2&ids=3

而不是预期

/search/findByIdIn?ids=1,2,3

这对于以与我的 Feign 客户端方法相同的方式声明的服务器 Spring Data REST 端点是正确的。

因此,由于这个问题,请求总是返回空集。

我看到过类似的 question,但看起来 Feign 客户端在 2015 年就像我预期的那样工作。

我正在使用:

spring-cloud-starter-feign 版本 1.2.4.RELEASE feign-httpclient 9.4.0 版 feign-core 版本 9.4.0

有没有办法纠正这种行为并将 Spring Cloud Feign Client 与 Spring Data REST 定义的端点“结合”?

【问题讨论】:

这可能会影响github.com/spring-cloud/spring-cloud-netflix/issues/1526。你可以试试 Dalston.SNAPSHOT,它引入了 spring-cloud-netflix 1.3.0.BUILD-SNAPSHOT。如果没有,你应该打开一个问题。 @spencergibb 确实是这样的行为:github.com/spring-cloud/spring-cloud-netflix/issues/1634 另请参阅示例项目:github.com/abinet/demo 【参考方案1】:

我有同样的问题,参数多次出现,而不是预期的逗号分隔的项目序列。解决方案非常简单:

在我的 feign 客户端中,我使用了数组

feignClient.get(new Long[]1L,2L,3L)

而不是集合/列表:

feignClient.get(Arrays.asList(1L,2L,3L))

【讨论】:

【参考方案2】:

在 Feign 中,您可以使用以下内容注释您的控制器

@CollectionFormat(feign.CollectionFormat.CSV) 它将处理集合

CSV 格式 findByIdIn?ids=1&ids=2&ids=3

【讨论】:

【参考方案3】:

我今天刚刚解决了这个问题,对我来说解决方案非常简单。

如果使用括号[] 表示查询数组:

Resources<MyClass> get(@RequestParam("ids[]") List<Long> ids);

它将创建一个看起来像这样的请求

/search/findByIdIn?ids[]=1&ids[]=2&ids[]=3

大多数服务器端框架会将其解释为数组。 如果您的服务器也在春季,那么您可以像这样选择它

@GetMapping("/search/findByIdIn")
public ResponseEntity findByIdIn(@RequestParam("ids[]") List<Long> ids)  ... 

请记住,查询必须被编码,[] 被编码为 %5B%5D

【讨论】:

【参考方案4】:

感谢 @prola 的回答。

只是添加一个显式示例,@CollectionFormat(feign.CollectionFormat.CSV) 注释针对一个方法;你不能全局应用到你的 Feign Client 界面。

所以每个方法都类似于:

@RequestMapping(value = ["/objects"], method = [RequestMethod.GET])
@CollectionFormat(feign.CollectionFormat.CSV)
fun findById(
    @RequestParam(value = "object.id", required = true) id: String,
    @RequestParam(value = "object.fields", required = false) objectFields: List<String> = DEFAULT_FIELDS_LIST,
    @RequestParam(value = "format") format: String = FORMAT,
): ResponseEntity<ObjectsDTO>

结果是

/objects?object.fields=size,weight,location 

而不是

/objects?object.fields=size&object.fields=weight&object.fields=location 

也可以参考:

1.16.Feign CollectionFormat support OpenFeign #542: Support Multiple Collection Formats

【讨论】:

以上是关于带有 List 参数的 Spring Cloud Feign Client @RequestParam 创建错误的请求的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Netflix:通过 RequestInterceptor 将主机请求参数传递给 FeignClient

Spring Cloud Vault 和带有 Vault 后端的 Spring Cloud Config 之间的区别

带有 OpenTracing 的 Spring Cloud Sleuth

带有spring-cloud的Spring Boot:gradle构建失败

如何在 spring-cloud-gateway 合约测试中从 spring-cloud-contract 中设置带有 StubRunner 端口的 url

带有 Spring-cloud-aws 和 cloudwatch 指标的 Spring Boot