通过feign传输localdatetime字段的时候丢失精度的问题

场景:A服务调用到B服务操作,通过Feign需要传递string参数和localdatetime参数过去,在测试的时候发现时间始终对不上。通过dubug后发现A服务传递的localdatetime参数正常,但是B服务接收到localdatetime参数缺失了"秒"

1. 请求侧A服务原代码:
    @ApiOperation("时间差值")
    @GetMapping(value = "/timeDifference")
     String timeDifference(@RequestParam(value = "startTime") LocalDateTime startTime, @RequestParam(value = "endTime") LocalDateTime endTime);
2. 被调用侧B服务原代码:
    @Resources
    @ApiOperation("获取两个时间之差")
    @GetMapping("/timeDifference")
    public ApiResponses<String> timeDifference(@RequestParam(value = "startTime") LocalDateTime startTime
            , @RequestParam(value = "endTime") LocalDateTime endTime) {
        return success(workdayService.workDayElapsedTime(startTime, endTime));
    }

问题描述详情:一开始我传递localdatetime是使用@RequestParam注解的,使用这个注解就相当于通过Feign调用服务的时候,将所需传递的参数拼接到URL后,一般传递字符类型的参数是没有问题,但是在传递localdatetime类型的参数时,未序列化造成了精度丢失。 当使用原来代码通过A服务使用Feign请求B服务时,请求的报文如下:

2021-07-14 16:21:43 INFO core.base.config.FeignLogger.log(46) 
	Client#timeDifference(LocalDateTime,LocalDateTime):
	---> POST http://B/b/timeDifference?startTime=21-7-13+%E4%B8%8B%E5%8D%885%3A53&endTime=21-7-13+%E4%B8%8B%E5%8D%885%3A53 HTTP/1.1
	---> END HTTP (0-byte body)

通过报文可知startTime、endTime都拼接到了url中传递过去,我们将url:

http:/B/b/remark/timeDifference?startTime=21-7-13+%E4%B8%8B%E5%8D%885%3A53&endTime=21-7-13+%E4%B8%8B%E5%8D%885%3A53

拿到网上在线URL网站解析,得到如下的结果: alt

错误日志:

alt

解决方案:

方案:入参将locadatetime类型转化为long传输,如:
LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))
1.请求测A服务修改为:
workDayFeignClient.timeDifference(applyTime.toEpochSecond(ZoneOffset.ofHours(8)), LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8))))

  @ApiOperation("获取已经耗时")
  @GetMapping(value = "/timeDifference")
  String timeDifference(@RequestParam(value = "startTime") long startTime
            , @RequestParam(value = "endTime") long endTime);
2.被调用侧B服务原代码:
    @Resources
    @ApiOperation("获取时间差值")
    @GetMapping("/timeDifference")
    public ApiResponses<String> timeDifference(@RequestParam(value = "startTime") long startTime
            , @RequestParam(value = "endTime") long endTime) {
        LocalDateTime startLocalDateTime = LocalDateTime.ofEpochSecond(startTime, 0, ZoneOffset.ofHours(8));
        LocalDateTime endLocalDateTime = LocalDateTime.ofEpochSecond(endTime, 0, ZoneOffset.ofHours(8));
        return success(workdayService.timeDifference(startLocalDateTime, endLocalDateTime));
    }

3.调用结果:

alt

总结

  • url带参传输方式,可能存在参数格式错误的情况。如对象传输需要先序列化,本次传输localdatetime也存在了该问题。在今后不止是使用Feign传输参数时,也多关注传输前后参数是否被转换出错的问题。*