问题

在最近的一次前后端对接的时候,我向前端传递了一个用雪花算法生成的 Long 类型的字段,该字段在数据库中的值如下:

1224972467449012226

直到自己用 swagger 测试了一下,发现结果如下:

1224972467449012200

原因

大致的原因显然是因为丢精

在Java中,Long 类型的最大值是 2^63-1 (9223372036854775807)

而在JS中,Number 类型的最大值为 2^53 (9007199254740992)

因此当Long类型的表示的数字过大时,就会出现丢精的问题,后面的数字用0填充

解决方案

解决 Long 类型与 Number 类型的精度问题,大致方案就是将 Long 类型转换为 String 类型,这样不管多长的数字,前端也都能够兼容。

一、修改get方法

1
2
3
4
private Long id;
public String getId(){
return ""+id;
}

这是相对于比较简单粗暴好理解的方法,缺点是对于使用 lombok 的懒癌程序员有点麻烦。

二、通过注解的方式改变序列化方式

1
2
@JsonSerialize(using=ToStringSerializer.class)
private Long id;

使用该注解需要导入 jackson 或者 fastjson 的依赖,该注解的作用是指定序列化的方式,这里特地指定用字符串的序列化方式。

三、通过配置的方式改变序列化方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class JsonConfig {
@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;
}
}

第三种方式在原理上与第二种方式类似,该配置属于全局配置,即将所有的 Long 类型序列化为字符串类型,相比与第二种方式更加方便,但有些时候前端并不希望你全部都传字符串