写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
这两天再项目中遇到了一些关于Date类型参数接收及返回的问题,还有返回前端Long类型参数损失精度的问题,整理一下解决方案。
首先说一下,在使用Postman或者ApiPost的时候关于Long类型损失精度的这种问题是体现不出来的,自己写的接口最好使用swagger进行测试。
项目中关于Date类型参数的问题描述:前端通过swagger调用后端接口,传了一个Date类型参数,按照时间范围查询,但是报400的错误,
此时后台也会报 Failed to convert from type [java.lang.String] to type [java.util.Date] 类似报错:
Date参数接收解决方案:
- 使用@DateTimeFormat注解标注参数,如:@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
网上提到的其它解决方式:
- 全局配置 在配置文件中添加如下配置
- 使用@JSONField注解,如:@JSONField(format = "yyyy-MM-dd HH:mm:ss")
以上两种我测试的是不行的,可能与我的环境有关,我的环境为 springboot 2.3.3.RELEASE + mybatisPlus3.4.0
以上虽然通过@DateTimeFormat注解解决了前端调用接口400的错误,但是返回的时间格式为:
2020-10-07T00:21:07.000+00:00,显然不是我们想要的,需要进一步处理,测试返回截图如下:
Date参数返回解决方案:
- 使用@JsonFormat注解标注参数,如:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
- 全局配置 在配置文件中添加如下配置
网上提到的其它解决方式
- 使用@JSONField注解,如:@JSONField(format = "yyyy-MM-dd HH:mm:ss")
以上这种我测试的是不行的!!!
还剩最后一个问题,就是返回的Long类型参数时区精度问题,我们数据库中的id为1313756222880563202,但是返回的为1313756222880563200,
关于精度损失的原因,从网上看了一些,大体意思就是:JavaScript 中能精准表示的最大整数是 2^{53} - 1,十进制为 9007199254740991。而Java的Long类型的有效位数是63位(扣除一位符号位),其最大值为2^{63}-1,十进制为9223372036854775807。只要java传给JavaScript的Long类型的值超过9007199254740991,就有可能产生精度丢失。
再提示一下,接口最好用swagger测试,这种精度损失问题使用Postman或者ApiPost是不体现的,截图如下,一切正常:
Long类型参数返回前端精度损失问题解决方案:
- 使用@JsonFormat注解标注参数,如:@JsonFormat(shape=JsonFormat.Shape.STRING)
- 全局配置 在配置文件中添加如下配置 :强制将所有数字全部转成字符串输出,这种方式的优点是使用方便,不需要调整代码;缺点是颗粒度太大,所有的数字都被转成字符串输出了,包括按照timestamp格式输出的时间也是如此。
- 自定义Jackson ObjectMapper springboot官方文档
@Configuration public class CustomJacksonObjectMapper { @Bean("jackson2ObjectMapperBuilderCustomizer") public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { Jackson2ObjectMapperBuilderCustomizer customizer = new Jackson2ObjectMapperBuilderCustomizer() { @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance) .serializerByType(Long.TYPE, ToStringSerializer.instance); } }; return customizer; } }
网上提到的其它解决方式
- 使用@JSONField注解,如:@JSONField(serializeUsing= ToStringSerializer.class)
以上这种我测试的是不行的!!!关于@JSONField注解为什么不行,而在有的项目中可以,明天再补充吧