正文参数不能与表单参数一起使用-带有Headers和json数据的Feign客户端

Posted

技术标签:

【中文标题】正文参数不能与表单参数一起使用-带有Headers和json数据的Feign客户端【英文标题】:Body parameters cannot be used with form parameters - Feign client with Headers and json data 【发布时间】:2017-09-21 12:44:33 【问题描述】:

我有一个这样的 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);

【问题讨论】:

【参考方案1】:

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

@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从最后一个参数移到了第一个参数,这样就成功了? 嗯,奇怪的是,改变参数的顺序也对我有用。就我而言,没有其他答案中提到的问题,所以我尝试了这个技巧(将请求主体对象作为第一个参数)并开始工作。还在挖掘中,如果找到其他原因,我会发布。 我认为这与这个问题有关github.com/OpenFeign/feign/issues/561,我认为他们在较新的版本中已修复,但似乎没有。【参考方案2】:

feign 中的参数顺序不应该像 spencergibb 在本期中所说的那样:https://github.com/spring-cloud/spring-cloud-netflix/issues/1915。如果您不将表单参数与正文参数一起使用,您应该搜索为什么您的参数之一被解释为表单参数。

我的具体问题是,使用 spring @RequestMapping 注释时,feign 错误解释了我的一个参数注释,因为一个错字,在我的情况下,我提供了一个请求路径值 /path/pathParam 并使用 @PathVariable( "pathparam") 小写拼写错误。

【讨论】:

【参考方案3】:

我有同样的错误,但不是因为参数的顺序。经调查发现问题出在我大摇大摆的定义中。我已经定义了路径中缺少的参数定义。即:

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

改为:

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

解决了这个问题。希望对遇到同样问题的人有所帮助。

【讨论】:

【参考方案4】:

如果还有人像我一样来这里,还有另一种可能的情况。 在使用查询参数和请求正文定义路径参数时,我遇到了同样的异常,如下所示:

    @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);

【讨论】:

以上是关于正文参数不能与表单参数一起使用-带有Headers和json数据的Feign客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何发送带有 URL 参数和 JSON 正文的 POST? [关闭]

将 Swagger 与 Django Rest Framework 一起使用,我可以在不同字段而不是一个正文中看到 POST 参数吗

与表单一起使用时,字符串参数不会自动解析为 bytes32

使用 Volley 在正文中发布表单数据参数

带有片段参数的 Grails render()

为啥子字符串不能与命令行参数一起使用?