Spring Cloud Feign客户端@RequestParam与List参数一起创建了错误的请求

13

我有一个Spring Cloud Feign客户端映射,定义如下:

@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

如果服务器的Spring Data REST端点以与我的Feign客户端方法相同的方式声明,则以下内容将正确。

因此,由于此问题,请求始终返回空集。

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

我正在使用:

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

是否有一种方法可以纠正行为并将Spring Cloud Feign客户端与Spring Data REST定义的端点结合起来?


这可能会产生影响 https://github.com/spring-cloud/spring-cloud-netflix/issues/1526。您可以尝试使用Dalston.SNAPSHOT,它会引入spring-cloud-netflix 1.3.0.BUILD-SNAPSHOT。如果不行的话,您应该打开一个问题。 - spencergibb
@spencergibb 确实看起来是这种行为:https://github.com/spring-cloud/spring-cloud-netflix/issues/1634 - Sergey Shcherbakov
请参考以下示例项目: https://github.com/abinet/demo - Sergey Shcherbakov
4个回答

12

我曾遇到过参数重复出现而不是预期的逗号分隔项序列的相同问题。解决方法非常简单:

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

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

而不是集合/列表:

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


5
在Feign中,您可以使用以下标记注释您的控制器:@CollectionFormat(feign.CollectionFormat.CSV),它将处理以CSV格式表示的集合。例如,findByIdIn?ids=1&ids=2&ids=3

4

感谢@prola的回答。

为了举一个明确的例子,@CollectionFormat(feign.CollectionFormat.CSV)注解针对一个方法;你不能将其全局应用于您的Feign客户端接口。

所以每个方法将类似于:

@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 

您还可以参考以下内容:

这个@CollectionFormat(feign.CollectionFormat.CSV)让我省了2天的时间,非常感谢。 - hbellahc
1
另一个选项是声明CSV格式,例如: @RequestLine( value = "GET "/books?categories={categories}", collectionFormat = CollectionFormat.CSV) - asokan

2
我今天刚刚遇到了这个问题,对我来说解决方案非常简单。
如果您使用方括号[]表示查询数组:
Resources<MyClass> get(@RequestParam("ids[]") List<Long> ids);

它将创建一个类似于这样的请求。
/search/findByIdIn?ids[]=1&ids[]=2&ids[]=3

大多数服务器端框架将把这个解释为一个数组。 如果您的服务器也是Spring,则可以像这样选择它

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接