feign post参数对象不加@RequestBody
最近在做小程序调支付服务接口的一个功能,这个feign接口传参真的太费事。
代码我就改造了下,不直接上真实代码。
比如小程序调支付服务的订单查询接口,支付服务那边的controller的订单查询方法是:
1
2
3
4
5
6
7
8
9
10
|
@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接口里参数对象应该是这么写的:
1
2
3
4
|
.... public Order qryBarcodePay( @RequestBody Order hero) throws Exception { .... } |
也就是传参的body前面一般会加上@RequestBody参数,但是支付服务的接口用到了@ApiImplicitParam和@ApiIgnore 注解,属于Swagger2的注解,有必要先学习下这两个注解的基本使用:
但是呢,一开始没想太多,调支付服务的feign接口的方法就按着平常写的post接口来:
1
2
3
4
5
6
7
|
@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接口改成这样子就正常了:
1
2
3
4
5
6
7
8
9
|
@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和原接口的参数
原接口:
1
2
3
4
5
|
@ApiImplicitParams ({ @ApiImplicitParam (name = "queryNum" , value = "查询流水" , paramType = "form" , required = true ), @ApiImplicitParam (name = "queryDate" , value = "流水日期" , paramType = "form" , required = false ) }) public Order qryBarcodePay( @ApiIgnore Order hero) |
feign接口:
1
2
3
4
|
@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接口方法上面加了
1
|
@Headers (MediaType.APPLICATION_FORM_URLENCODED_VALUE) |
其次require=true就表示这两个参数是必传的。
以上就确定了feign的接口方法应该如何写,最后参数到原接口过来时,会自动将queryNum、queryDate两个参数set到Order对象里去,至于为何,我也不太清楚,暂时知道是可以这么用的。
使用@RequestParam、@RequestBody 的正确姿势
背景
最近在使用 @RequestParam、@RequestBody 注解定义 feign 接口的时候出现一些使用上的问题,造成调用方启动的时候会报错。
详细情况
第一种情况,如下:
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2(String name1); |
接口有且只有一个 key/value 参数,此时可以不必在 name1 参数上使用 @RequestParam 注解。通过 Feign 调用该接口的调用方可以正常启动。
第二种情况,如下:
1
2
|
@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 值不允许为空,正确的姿势如下:
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2( @RequestParam ( "name1" ) String name1); |
第三种情况,如下:
1
2
|
@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 注解,正确的姿势如下:
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2( @RequestParam (“name1”) String name1, @RequestParam (“name2”) String name2); |
小结一下
在使用 @RequestParam 注解的时候,value 值必须设置,如下:
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2( @RequestParam (“name1”) String name1); |
如果接口有且只有一个参数,并且该参数是 key/value 类型,则无需为该参数设置 @RequestParam 注解,如下:
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2(String name1); |
接口存在多个参数(key/value、Json 对象)的时候,每个 key/value 类型的参数必须显示的指定 @RequestParam 注解,且必须设置对应的 value
1
2
|
@PostMapping (value = "/hello2" ) BetaDto hello2( @RequestParam (“name1”) String name1, RequestParam(“name2”) String name2, BetaDto betaDto); |
接口无论有多个参数还是一个参数,都不需要为 Json 对象参数显示的指定 @RequestBody 注解
1
2
3
4
|
@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
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/miaokezhang/article/details/108596544