本文用示例介绍SpringBoot如何解决雪花算法主键ID传到前端后精度丢失问题。
问题描述Java后端Long类型的范围
-2^63~2^63,即:-9223372036854775808~9223372036854775807,它是19位的。
这个数字可以通过方法获得:Long.MAX_VALUE、Long_MIN_VALUE。
前端JS的数字类型的范围
-2^53~2^53,即:-9007199254740991~9007199254740991,它是16位的。
这个数字可以通过方法获得:Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER。
结论
可见,Java后端的Long宽度大于前端的。雪花算法一般会生成18位或者19位宽度的数字,那么这时就会出问题。
项目场景1.表结构
主键类型是BIGINT,存储雪花算法生成的ID。
2.Entity
用Long 类型对应数据库ID的BIGINT类型。
这里使用 MybatisPlus 的雪花算法自动生成19位长度的纯数字作为主键ID。(当然也可以手动用雪花算法生成ID)
3.响应给前端
以JSON数据响应给前端正常
问题描述 实例Controller
Entity
测试
访问:http://localhost:8080/user/find?id=1352213368413982722
结果
问题复现从上边可以看到,并没有问题。
为什么没有出问题?
前端传入后端:SpingMVC会自动将String类型的ID转为Long类型,不会出问题
后端响应给前端:是JSON格式,与JS没有关系,不会出问题
什么时候会出问题?
前端接收到JSON之后,将其序列化为JS对象,然后进行其他操作。在JSON转JS对象时就会出问题,如下:
可以看到,原来id为1352213368413982722,序列化为JS对象后变成了 1352213368413982700
代码为:
解决方案有如下两种方案
1.将数据库表设计的id字段由 Long 类型改成 String 类型。
2.前端用String类型来保存ID保持精度,后端及数据库继续使用Long(BigINT)类型
方案1使用String 类型做数据库ID,查询性能会大幅度下降。所以应该采用方案2。本文介绍方案2。
全局处理简介
自定义ObjectMapper。
方案1:ToStringSerializer(推荐)
测试
访问:http://localhost:8080/user/find?id=1352213368413982722
方案2:自定义序列化器(不推荐)
序列化器
ObjectMapper配置
测试
访问:http://localhost:8080/user/find?id=1352213368413982722
局部处理说明
在字段上加:@JsonSerialize(using= ToStringSerializer.class)。
实例
测试
访问:http://localhost:8080/user/find?id=1352213368413982722
到此这篇关于SpringBoot主键ID传到前端后精度丢失的问题解决的文章就介绍到这了,更多相关SpringBoot主键ID精度丢失内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!