· 尚可 · 工程技术 · 4 分钟阅读

Feign中传参使用的注解

Feign中传参使用的注解

今天遇到一个需求,需要异步导出一些数据到文件中,因为导出的数据量比较大,所以接收到导出请求之后,就将需要导出的数据的ID写入了MQ中,消费端接收到MQ的消息之后,然后通过Feign调用其他的服务进行数据导出。 通过Fei…

今天遇到一个需求,需要异步导出一些数据到文件中,因为导出的数据量比较大,所以接收到导出请求之后,就将需要导出的数据的ID写入了MQ中,消费端接收到MQ的消息之后,然后通过Feign调用其他的服务进行数据导出。

通过Feign调用的代码如下:

@FeignClient(name = ConstantsUtil.ORDER_SERVICE)
public interface OrderService {
    
    @Headers({"feign: true"})
    @PostMapping(value = "/orders/save")
    void save(@RequestParam("json") String json);

}

开发的过程中,数据量比较少,通过此方法可以正常的完成调用,但是在测试环境,当数据量(json)稍微大一点之后,服务就无法调用了,直接报错了。

通过查询日志发现,Feign调用时,请求的地址居然是http://order.service?json=xxxxxxx,由于json的数据量比较大,所以请求的时候直接就报错了。

看到这里之后,基本可以确定问题了:传输的数据量太大了导致URL太长了,解决方案就是把数据放在RequestBody中传输,修改代码如下:

@FeignClient(name = ConstantsUtil.ORDER_SERVICE)
public interface OrderService {
    
    @Headers({"feign: true"})
    @PostMapping(value = "/orders/save")
    void save(@RequestBody String json);

}

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中的占位符到目标方法中。

    @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之间关系之后,回到最初的那段代码,有没有觉得有点奇怪呢?

@PostMapping(value = "/orders/save")
void save(@RequestParam("json") String json);

发出一个POST(@PostMapping(value = "/orders/save") )请求,但是请求参数却被绑定在URL(@RequestParam("json") )后面。。。

其实也好理解,POST请求体里是空的,请求的参数就是在URL后面,后端取参数的时候,也是用@RequestParam取的。

Share:
返回文章列表
SpringBoot中线程池使用
工程技术

SpringBoot中线程池使用

最近接手的项目遇到一个这样的问题:我们服务的一个接口需要循环查询另一个服务的接口,这样如果数据量较多的时候,我们服务的接口响应时间可能就会超时,伪代码如下: 这里先不讨论为什么不能让对方服务提供一个批量查询接口,然后通过…

领域驱动设计
工程技术

领域驱动设计

复杂软件设计的解决方案 DDD是Domain-Driven Design(领域驱动设计)的简称,它是一种解决复杂软件设计的方法论,它试图分离技术实现的复杂性,并围绕业务概念构建的领域模型,以解决软件难以理解,难以演进的问…

什么是CAP定理
工程技术

什么是CAP定理

什么是CAP定理? CAP定理告诉我们,一个分布式系统不可能同时满足一致性(C:Consistency),可用性(A: Availability)和分区容错性(P:Partition tolerance)这三个基本需求,…