解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

这两天再项目中遇到了一些关于Date类型参数接收及返回的问题,还有返回前端Long类型参数损失精度的问题,整理一下解决方案。

首先说一下,在使用Postman或者ApiPost的时候关于Long类型损失精度的这种问题是体现不出来的,自己写的接口最好使用swagger进行测试。

项目中关于Date类型参数的问题描述:前端通过swagger调用后端接口,传了一个Date类型参数,按照时间范围查询,但是报400的错误,

解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第1张图片

此时后台也会报 Failed to convert from type [java.lang.String] to type [java.util.Date] 类似报错:

Date参数接收解决方案:

  1. 使用@DateTimeFormat注解标注参数,如:@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

网上提到的其它解决方式:

  1. 全局配置  在配置文件中添加如下配置                      

    解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第2张图片

  2. 使用@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,显然不是我们想要的,需要进一步处理,测试返回截图如下:

解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第3张图片

Date参数返回解决方案:

  1. 使用@JsonFormat注解标注参数,如:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")       
  2. 全局配置  在配置文件中添加如下配置                      
     

解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第4张图片

网上提到的其它解决方式

  1. 使用@JSONField注解,如:@JSONField(format = "yyyy-MM-dd HH:mm:ss")

以上这种我测试的是不行的!!!

还剩最后一个问题,就是返回的Long类型参数时区精度问题,我们数据库中的id为1313756222880563202,但是返回的为1313756222880563200,

 

解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第5张图片

关于精度损失的原因,从网上看了一些,大体意思就是:JavaScript 中能精准表示的最大整数是 2^{53} - 1,十进制为 9007199254740991。而Java的Long类型的有效位数是63位(扣除一位符号位),其最大值为2^{63}-1,十进制为9223372036854775807。只要java传给JavaScript的Long类型的值超过9007199254740991,就有可能产生精度丢失。

再提示一下,接口最好用swagger测试,这种精度损失问题使用Postman或者ApiPost是不体现的,截图如下,一切正常:

解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第6张图片

Long类型参数返回前端精度损失问题解决方案:

  1. 使用@JsonFormat注解标注参数,如:@JsonFormat(shape=JsonFormat.Shape.STRING)
  2. 全局配置  在配置文件中添加如下配置 :强制将所有数字全部转成字符串输出,这种方式的优点是使用方便,不需要调整代码;缺点是颗粒度太大,所有的数字都被转成字符串输出了,包括按照timestamp格式输出的时间也是如此。 

    解决springboot接收Date类型参数、返回Date类型参数、返回Long类型参数精度丢失问题_第7张图片

  3. 自定义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;
        }
    }
          

网上提到的其它解决方式

  1. 使用@JSONField注解,如:@JSONField(serializeUsing= ToStringSerializer.class)

以上这种我测试的是不行的!!!关于@JSONField注解为什么不行,而在有的项目中可以,明天再补充吧

             

 

你可能感兴趣的:(springboot)