Feign接口调用GET请求@RequestParam传参丢失

69 篇文章 0 订阅
9 篇文章 0 订阅

问题现象

  • 项目使用的是Spring Cloud微服务,服务间调用使用的是Feign
  • 在一次服务调用时,发现GET传参丢失,没有传递过去任何参数
  • 加了@RequestParam注解,发现还是传参失败
  • 传递的参数有2个,1个是一个Long类型主键ID,一个是查询VO

排查解决

Feign介绍

  • Feign是一种声明式的Web服务客户端,它使得编写Web服务客户端变得更简单
  • 通过使用Feign,我们可以定义一个接口,并使用注解的方式来声明对远程服务的调用
  • Feign会根据接口的定义,自动构造出符合目标服务的HTTP请求,并处理HTTP响应
  • Feign还集成了Ribbon负载均衡的能力,可以轻松地实现对多个服务实例的负载均衡调用
  • Feign的主要特性包括:
    • 声明式的API:通过定义接口和使用注解的方式,简化了对远程服务的调用。
    • 支持多种HTTP方法:包括GET、POST、PUT、DELETE等。
    • 支持路径参数、查询参数、请求体参数等多种参数的传递方式。
    • 支持表单提交和文件上传。
    • 支持请求和响应的拦截器,可以对请求和响应进行自定义处理。
    • 集成了Ribbon负载均衡的能力,可以轻松实现对多个服务实例的负载均衡调用。
  • 总的来说,Feign是一个非常方便的服务调用框架,可以极大地简化我们对远程服务的调用代码,提高开发效率。

GET加注解解决

  • 要使用GET只能将封装的查询VO改为一个个参数
  • 确保在Feign接口的对应请求方法上正确使用@RequestParam注解,并传入正确的参数名称
  • 确保@RequestParam注解中指定的参数类型与Feign接口中方法的参数类型一致
  • 在服务的接口方和调用方,都要使用@RequestParam注解,服务方标明接收GET请求

使用POST方式解决

  • @RequestParam针对单个参数可以使用,对于对象示例无法使用
  • 但是传递多个参数时,使用对象封装比较简单,也比较优雅
  • 这就需要使用@RequestBody注解,只能使用POST方式
  • 最终测试发现,使用POST方式传参,同时增加 @RequestBody注解,可以解决这个问题
  • 同样,在服务的接口方和调用方,都要使用@RequestBody注解,服务方标明接收POST请求
  • 服务提供方代码:
@RestController
@RequestMapping("/api/statistics/query")
public class StatisticsQueryController {
    /**
     * 获取路口过车流量统计
     * @param queryVO
     * @return
     */
    @PostMapping(value = "/getIntersectionFlowList")
    public ResponseEntity<List<IntersectionFlowVO>> getIntersectionFlowList(@RequestBody IntersectionFlowQueryVO queryVO) {
        log.info("getIntersectionFlowList 查询参数:{}", JSON.toJSONString(queryVO));
        return ResponseEntity.ok().body(statisticsQueryService.getIntersectionFlowList(queryVO));
    }
}
  • 使用方接口代码:
@AuthorizedFeignClient(name = "DataAnalysis", url = "${microservices.dataanalysis}")
@Component
public interface DataAnalysis {
    /**
     * 获取路口过车流量统计
     * @param queryVO
     * @return
     */
    @PostMapping(value = "/statistics/query/getIntersectionFlowList")
    ResponseEntity<List<IntersectionFlowVO>> getIntersectionFlowList(@RequestBody IntersectionFlowQueryVO queryVO);
}
  • 使用时,注入接口即可
	@Autowired
    private DataAnalysis dataAnalysis;
    
	ResponseEntity<List<IntersectionFlowVO>> responseEntity = dataAnalysis.getIntersectionFlowList(queryVO);

时间戳传参失败

报错现象

  • 解决传参问题后,发现在传递时间戳类型timeStamp参数时,解析失败
  • 主要是格式问题,无法解析,报错如下:
2023-08-31 15:36:23.971 ERROR 78816 --- [  XNIO-1 task-7] SituationAnalysisIntersectionExtentService : getEventDetailList:
Error while extracting response for type [java.util.List<com.newatc.api.situationanalysis.vo.SituationAnalysisIntersectionVO>] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: 
Cannot deserialize value of type `java.time.Instant` from String "2023-08-31 15:35:05": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text '2023-08-31 15:35:05' could not be parsed at index 10; 
nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.Instant` from String "2023-08-31 15:35:05": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text '2023-08-31 15:35:05' could not be parsed at index 10
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 2, column: 17] 
 (through reference chain: java.util.ArrayList[0]->com.newatc.api.situationanalysis.vo.SituationAnalysisIntersectionVO["timeStamp"])
  • 由于两边的程序,使用的是不同的日期参数类型,一边是Date,一边是Instant,无法调和

原因与解决

  • 这个错误通常是因为在JSON反序列化过程中,字符串类型的时间戳无法正确地转换为Java 8中的Instant类型
  • 网上有一些解决方式,例如重写反序列化的方法,感觉比较麻烦,没有使用
  • 最终决定传参时,统一使用StringYYYY-MM-dd HH:mm:ss字符串传参,问题解决
  • 也有说使用注解或者配置,指定日期格式的,有兴趣的朋友可以试试
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持是一种态度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值