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