身体参数不能与表单参数一起使用 - 使用头和json数据的Feign客户端

20

我有一个像这样的FeignClient

@RequestLine("POST /enroll")
@Headers({ "header1: {header1}", "header2: {header2}", "Content-Type: application/json" })
ResponseDto enroll(@Param("header1") String header1,@Param("header1") String header1, RequestDto requestDto)throws MyCustomException;

我没有使用Spring Cloud Netflix。但是我一直收到以下异常。

Caused by: java.lang.IllegalStateException: Body parameters cannot be used with form parameters.
at feign.Util.checkState(Util.java:128)
at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:112)
at feign.Contract$BaseContract.parseAndValidatateMetadata(Contract.java:64)
at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:146)
at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:53)
at feign.Feign$Builder.target(Feign.java:209)
at feign.Feign$Builder.target(Feign.java:205)

我是这样实例化我的客户端的。

return Feign.builder()
        .encoder(new JacksonEncoder())
        .decoder(new JacksonDecoder())
        .logger(new Slf4jLogger())
        .logLevel(Logger.Level.FULL)
        .target(RegularFeignClient.class, url);
4个回答

29

哇,这是一个棘手的问题。在这里参数的顺序很重要。

@RequestLine("POST /enroll")
@Headers({ "header1: {header1}", "header2: {header2}", "Content-Type: application/json" })
ResponseDto enroll(RequestDto requestDto, @Param("header1") String header1,@Param("header1") String header1)throws MyCustomException;

这个可行!!!

多亏了我的资深开发人员。他找到了它。


那么你把 RequestDto requestDto 从最后一个参数移到了第一个,就解决问题了? - Tim Büthe
1
嗯,奇怪的是,改变参数顺序对我也起作用了。在我的情况下,没有像其他答案中提到的问题,所以我尝试了这个技巧(将请求体对象作为第一个参数),它开始工作了。仍在探究,如果我找到任何其他原因,我会发布它。 - human
我认为这与此问题有关 https://github.com/OpenFeign/feign/issues/561,我以为他们在更新的版本中修复了它,但似乎并没有。 - ascetic652

10

根据spencergibb在此问题中的陈述,feign中参数的顺序不应该影响使用:https://github.com/spring-cloud/spring-cloud-netflix/issues/1915。如果您没有同时使用表单参数和请求体参数,则应查找为什么其中一个参数被解释为表单参数。

我的具体问题是,在使用Spring的@RequestMapping注释时,由于一个小写的错别字,feign误解了我的一个参数注释。在我的情况下,我提供了一个请求路径值/path/{pathParam},并将Spring注释与@PathVariable("pathparam")的小写错别字一起使用。


2
如果还有像我一样来到这里的人,这里有另一个可能的情况。当定义路径参数、查询参数和请求体时,我遇到了相同的异常,如下所示:
    @RequestLine("POST /namespaces/{namespace}/releases/{release}")
    Response createRelease(ReleaseBody releaseBody,
                           @Param("namespace") String namespace,
                           @Param("release") String release,
                           @Param("plan") String planName);

即使更新到最新的feign,我仍然收到异常IllegalStateException: Body parameters cannot be used with form parameters.

在请求行中明确定义查询参数可以解决问题:

    @RequestLine("POST /namespaces/{namespace}/releases/{release}?plan={plan}")
    Response createRelease(ReleaseBody releaseBody,
                           @Param("namespace") String namespace,
                           @Param("release") String release,
                           @Param("plan") String planName);

1

我遇到了同样的错误,但并不是因为参数顺序的问题。经过调查发现问题出在我的Swagger定义上。我定义了一个缺失路径中参数定义的参数定义。例如:

     /someapi/bla/{parm1}/bla/
       parameters:
          - $ref: '#/parameters/parm1'
          - $ref: '#/parameters/parm2'

改为:

已更改:

     /someapi/bla/{parm1}/bla/
       parameters:
          - $ref: '#/parameters/parm1'

问题已解决。希望能帮助到遇到相同问题的人。


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