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


    问题现象

    • 项目使用的是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));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 使用方接口代码:
    @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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 使用时,注入接口即可
    	@Autowired
        private DataAnalysis dataAnalysis;
        
    	ResponseEntity<List<IntersectionFlowVO>> responseEntity = dataAnalysis.getIntersectionFlowList(queryVO);
    
    • 1
    • 2
    • 3
    • 4

    时间戳传参失败

    报错现象

    • 解决传参问题后,发现在传递时间戳类型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] 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"])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 由于两边的程序,使用的是不同的日期参数类型,一边是Date,一边是Instant,无法调和

    原因与解决

    • 这个错误通常是因为在JSON反序列化过程中,字符串类型的时间戳无法正确地转换为Java 8中的Instant类型
    • 网上有一些解决方式,例如重写反序列化的方法,感觉比较麻烦,没有使用
    • 最终决定传参时,统一使用StringYYYY-MM-dd HH:mm:ss字符串传参,问题解决
    • 也有说使用注解或者配置,指定日期格式的,有兴趣的朋友可以试试
  • 相关阅读:
    电路设计篇【5】MOS管驱动电路设计,如何让MOS管快速开启和关闭?
    新闻软文稿件媒体发布怎么做?纯干货
    Web3社交资料池
    【C++】类与对象 第二篇(构造函数,析构函数,拷贝构造,赋值重载)
    【三维目标检测】VoteNet(一)
    运动用品品牌排行榜,2022年值得买的运动用品推荐
    36.一文讲透JavaScript日期对象Date,时间戳、1970、date方法、date计算
    一次服务器被入侵的处理过程分享
    ppo-clip的本质以及它为什么是另一种ppo-KL-penalty
    合并区间【贪心算法】
  • 原文地址:https://blog.csdn.net/u010882234/article/details/132673955