欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

feign post参数对象不加@RequestBody的使用说明

程序员文章站 2022-06-10 14:51:19
目录feign post参数对象不加@requestbody使用@requestparam、@requestbody 的正确姿势feign post参数对象不加@requestbody最近在做小程序调...

feign post参数对象不加@requestbody

最近在做小程序调支付服务接口的一个功能,这个feign接口传参真的太费事。

代码我就改造了下,不直接上真实代码。

比如小程序调支付服务的订单查询接口,支付服务那边的controller的订单查询方法是:

 @responsebody
    @requestmapping(value = "/order/select", method = requestmethod.post)
    @apioperation(value = "订单查询", notes = "订单查询")
    @apiimplicitparams({
            @apiimplicitparam(name = "querynum", value = "查询流水", paramtype = "form", required = true),
            @apiimplicitparam(name = "querydate", value = "流水日期", paramtype = "form", required = false)
    })
    public order qrybarcodepay(@apiignore order hero) throws exception {
        xxxxx;
    }

这个post接口,有点奇怪,多了很多没见过的注解,而一般情况,post接口里参数对象应该是这么写的:

....
public order qrybarcodepay(@requestbody order hero) throws exception {
....
}

也就是传参的body前面一般会加上@requestbody参数,但是支付服务的接口用到了@apiimplicitparam和@apiignore 注解,属于swagger2的注解,有必要先学习下这两个注解的基本使用:

  • @apiimplicitparam的使用
  • @apiignore注解的使用

但是呢,一开始没想太多,调支付服务的feign接口的方法就按着平常写的post接口来:

@feignclient(name="pay", path="pay")
public interface payfeignclient {
    @responsebody
    @requestmapping(value = "/payment/order/select", method = requestmethod.post)
    @apioperation(value = "订单查询", notes = "订单查询")
    public order qrybarcodepay(@requestbody order order);
}

然后在调式的时候,发现小程序调支付服务这个订单查询接口的时候,支付服务那边接受的参数对象order字段里面的值都是null,原因是feign这边传的order对象是requestbody类型,而支付服务那边的接口接受参数时没有加@requestbody,所以应该是反序列化的时候,由于格式不同,就没有成功,才出现了支付服务这边接受的参数对象order字段里面的值都为null。

解决办法:

feign接口改成这样子就正常了:

@feignclient(name="pay", path="pay")
public interface payfeignclient {
    @requestmapping(value = "/payment/qry/barcode/pay", method = requestmethod.post)
    @apioperation(value = "订单查询", notes = "订单查询")
    @headers(mediatype.application_form_urlencoded_value)
    public resultinfo<qrybarcodepaymodel> qrybarcodepay(
            @requestparam(required = true, name = "qryno") string qryno,
            @requestparam(required = true, name = "hotelcode") string hotelcode);
}

这里对比一下feign和原接口的参数:

原接口:

@apiimplicitparams({
            @apiimplicitparam(name = "querynum", value = "查询流水", paramtype = "form", required = true),
            @apiimplicitparam(name = "querydate", value = "流水日期", paramtype = "form", required = false)
    })
    public order qrybarcodepay(@apiignore order hero)

feign接口:

@headers(mediatype.application_form_urlencoded_value)
    public resultinfo<qrybarcodepaymodel> qrybarcodepay(
            @requestparam(required = true, name = "qryno") string qryno,
            @requestparam(required = true, name = "hotelcode") string hotelcode);

可以看出来差别很大,首先传参,原接口是post请求,传的是一个对象,但是对象前加了@apiignore 注解,相信前面给的链接学习后知道这个注解表示的是忽略的意思,也就是传参的时候,忽略掉这个对象,所以feign传的参压根就没有对象。

其次原接口对两个参数加了@apiimplicitparam,需要提前说明的是,加了@apiimplicitparam的两个参数querynum、querydate都属于order 类里的属性。

重点看@apiimplicitparam的paramtype = “form”, required = true这两个地方,paramtype="form"就表示传参以form表单的形式,所以feign接口方法上面加了

@headers(mediatype.application_form_urlencoded_value)

其次require=true就表示这两个参数是必传的。

以上就确定了feign的接口方法应该如何写,最后参数到原接口过来时,会自动将querynum、querydate两个参数set到order对象里去,至于为何,我也不太清楚,暂时知道是可以这么用的。

使用@requestparam、@requestbody 的正确姿势

背景

最近在使用 @requestparam、@requestbody 注解定义 feign 接口的时候出现一些使用上的问题,造成调用方启动的时候会报错。

详细情况

第一种情况,如下:

@postmapping(value = "/hello2")
betadto hello2(string name1);

接口有且只有一个 key/value 参数,此时可以不必在 name1 参数上使用 @requestparam 注解。通过 feign 调用该接口的调用方可以正常启动。

第二种情况,如下:

 @postmapping(value = "/hello2")
betadto hello2(@requestparam string name1);

接口有且只有一个 key/value 参数,此时如果对 name1 参数上使用 @requestparam 注解,此时通过 feign 调用该接口的调用方可启动的时候回抛出如下错误:

caused by: java.lang.illegalstateexception: requestparam.value() was empty on parameter 0

意思是 @requestparam 的 value 值不允许为空,正确的姿势如下:

 @postmapping(value = "/hello2")
betadto hello2(@requestparam("name1") string name1);

第三种情况,如下:

@postmapping(value = "/hello2")
betadto hello2(string name1, string name2);

接口存在多个 key/value 参数,此时通过 feign 调用该接口的调用方启动的时候会抛出如下错误:

caused by: java.lang.illegalstateexception: method has too many body parameters

像这种多参数(key/value)的情况必须为每个参数增加 @requestparam 注解,正确的姿势如下:

@postmapping(value = "/hello2")
betadto hello2(@requestparam(“name1”)  string name1, @requestparam(“name2”)  string name2);

小结一下

在使用 @requestparam 注解的时候,value 值必须设置,如下:

@postmapping(value = "/hello2")
betadto hello2(@requestparam(“name1”)  string name1);

如果接口有且只有一个参数,并且该参数是 key/value 类型,则无需为该参数设置 @requestparam 注解,如下:

@postmapping(value = "/hello2")
betadto hello2(string name1);

接口存在多个参数(key/value、json 对象)的时候,每个 key/value 类型的参数必须显示的指定 @requestparam 注解,且必须设置对应的 value

@postmapping(value = "/hello2")
betadto hello2(@requestparam(“name1”) string name1, requestparam(“name2”) string name2, betadto betadto);

接口无论有多个参数还是一个参数,都不需要为 json 对象参数显示的指定 @requestbody 注解

@postmapping(value = "/hello1")
betadto hello1(betadto betadto);
@postmapping(value = "/hello2")
betadto hello2(@requestparam(“name1”) string name1, requestparam(“name2”) string name2, betadto betadto);

每个接口里只允许有一个 json 对象类型的参数,否则通过 feign 调用该接口的调用方启动的时候会抛出如下错误:

caused by: java.lang.illegalstateexception: method has too many body parameters

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。