Feign中传参使用的注解
今天遇到一个需求,需要异步导出一些数据到文件中,因为导出的数据量比较大,所以接收到导出请求之后,就将需要导出的数据的ID写入了MQ中,消费端接收到MQ的消息之后,然后通过Feign调用其他的服务进行数据导出。
通过Feign调用的代码如下:
1 | @FeignClient(name = ConstantsUtil.ORDER_SERVICE) |
开发的过程中,数据量比较少,通过此方法可以正常的完成调用,但是在测试环境,当数据量(json)稍微大一点之后,服务就无法调用了,直接报错了。
通过查询日志发现,Feign调用时,请求的地址居然是http://order.service?json=xxxxxxx
,由于json的数据量比较大,所以请求的时候直接就报错了。
看到这里之后,基本可以确定问题了:传输的数据量太大了导致URL太长了,解决方案就是把数据放在RequestBody中传输,修改代码如下:
1 | @FeignClient(name = ConstantsUtil.ORDER_SERVICE) |
Feign调用的时候,把数据放在RequestBody中,在被调用端接收数据的时候,也用@RequestBody绑定要接收的参数即可。
经过上面的调整,再在测试环境保存数据,调用的时候就没有报错了。
在使用Feign进行参数绑定时,我们通过会用到三个注解:@RequestParam、@RequestBody、@PathVariable,这三者之间有何区别呢?
@RequestParam
一般用来处理Content-Type
为application/x-www-form-urlencoded
编码的内容。
即可以传递单个参数,也可以传递对象。如果传递对象,其实就是利用key-value组成map,然后反射成我们需要的对象。
注意:在Http请求中,如果不指定Content-Type
则默认为application/x-www-form-urlencoded
。@RequestBody
一般用来处理Content-Type
不为application/x-www-form-urlencoded
编码的内容,比如application/json
。
一般用来传递对象,也可以传递单个参数。但是GET
请求不能使用@RequestBody
获取数据,因为没有HttpEntity
。@PathVariable
一般用来映射URL中的占位符到目标方法中。1
2@GetMapping("/order/{id}")
JsonResult findById(@PathVariable("id") Integer id);
HTTP的GET
、POST
请求和Content-Type
之间有什么关系呢?
GET
和POST
都定义了数据提交的方式:GET
请求是将form
数据拼装在URL后面提交;POST
请求是将数据放在RequestBody中提交。
Content-Type定义了数据编码的方式,application/x-www-form-urlencoded
方式是将form
的数据转成K-V
的形式然后形成一个字符串,拼接在URL后面,form
中的多个参数以?
分割;application/json
方式是将数据转成json
格式。
搞清楚了GET
、POST
请求和Content-Type
之间关系之后,回到最初的那段代码,有没有觉得有点奇怪呢?
1 | @PostMapping(value = "/orders/save") |
发出一个POST
(@PostMapping(value = "/orders/save")
)请求,但是请求参数却被绑定在URL
(@RequestParam("json")
)后面。。。
其实也好理解,POST
请求体里是空的,请求的参数就是在URL后面,后端取参数的时候,也是用@RequestParam
取的。