文章目录
- 抛出问题
- 解决问题
- 解决方法1:
- 解决方法2:
- 解决方法3:
- <font color=gree>解决方法:4
抛出问题
Java 服务端如果直接返回 Long
整型数据给前端,Javascript
会自动将其转换为 Number
类型(注:此类型为双精度浮点数,表示原理与取值范围等同于 Java 中的 Double
)。
Long
类型能表示的最大值是
2
63
2^{63}
263 - 1,在取值范围之内,超过
2
53
2^{53}
253(9007199254740992)的数值转化为 Javascript
的 Number
时,数值会产生精度损失。
扩展说明,在
Long
取值范围内,任何 2 的指数次的整数都是绝对不会存在精度损失的,所以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸,双精度浮点数的尾数位只有52 位。
解决问题
解决方法1:
对于需要使用超大整数的场景,服务端使用 String 字符串类型返回。
服务端与前端交互使用 String 类型,这样就不会存在精度损失问题,与数据库里是的Long 类型主键交互记得转换下就行。
(这里不建议用字符型做主键,会有索引上的性能损耗)
解决方法2:
如果使用的是 Jackson 序列包的话, 在 id 值上加如下注解.
/**
* 用户ID
* 将Long类型数字进行json格式转化时,转成String格式类型
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
如果使用的是 fastjson序列包的话, 在 id 值上加如下注解.
@JSONField(serializeUsing = String.class)
private Long id;
缺点就是 需要在每个类的对应属性上加, 如果类很多的话,工作量还是蛮大的.
解决方法3:
因为服务端与前端交互都是通过 Json 格式的数据交互的,所以我们这要做一个全局配置告诉我们的JSON转换器,再遇到Long类型的属性时自动转换为String类型即可。
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder){
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 全局配置序列化返回 JSON 处理
SimpleModule simpleModule = new SimpleModule();
//JSON Long ==> String
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
解决方法:4
Springboot项目,在配置文件中添加一句即可。
spring.jackson.generator.write_numbers_as_strings = true