前言
在前后端分离的开发中,数据库里存的主键 id 明明是:1750433246798835714,但是前端接收到数据后,id 却变成了:1750433246798835700,后几位莫名其妙变成了 0!
导致的结果就是:
前端拿这个错误的 id 去查询详情或执行删除操作时,后端直接报错“数据不存在”,因为 id 对不上。
原因分析
这个问题的根源在于 java 和 javascript 对数字处理机制的不同。
java 中的 long 类型是 64 位有符号整数,它的取值范围非常大;
而常用的雪花算法 (snowflake) 生成的 id 通常就是 19 位的,完全在 java 的 long 范围内。
javascript 中并没有专门的整数类型,所有的数字本质上都是 ieee 754 标准的双精度浮点数(double)。
js 能安全表示的最大整数(safe integer)是253-1,这就导致后端的 19 位 id传给前端时,因为超过了 js 的安全整数范围,js 就会发生精度丢失,自动进行“四舍五入”或者直接丢弃低位,导致后几位变成 0。
解决方案
要解决这个问题,最简单有效的方法是:
后端在返回数据给前端时,把 long 类型的数据统统转换成 string(字符串)类型。
因为字符串在 js 里是绝对安全的,不会发生精度丢失。
不需要手动去改每一个 dto 或 vo 类,只需要在 spring boot 中加一个全局配置类,利用 jackson 的序列化机制自动完成转换。
直接在 config 包下新建一个类jsonconfig.java:
/**
* spring mvc全局json配置
* 用于解决 long 类型精度丢失问题
*/
@jsoncomponent
public class jsonconfig {
/**
* 全局配置:将 long 类型序列化为 string
*/
@bean
public objectmapper jacksonobjectmapper(jackson2objectmapperbuilder builder) {
// 创建 objectmapper
objectmapper objectmapper = builder.createxmlmapper(false).build();
// 创建自定义序列化模块
simplemodule module = new simplemodule();
// 将 long 类(包装类)和 long(基本类型)都序列化为字符串
// tostringserializer.instance 会调用对象的 tostring() 方法
module.addserializer(long.class, tostringserializer.instance);
module.addserializer(long.type, tostringserializer.instance);
// 注册模块
objectmapper.registermodule(module);
return objectmapper;
}
}使用这种全局配置 方案,可以一劳永逸地解决项目中所有 long 类型精度丢失的问题。
总结
到此这篇关于后端long类型id传给前端精度丢失(变00)的原因分析及解决方案的文章就介绍到这了,更多相关后端long类型传前端精度丢失内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论