后端Long類型ID傳給前端精度丟失(變00)的原因分析及解決方案
前言
在前后端分離的開發(fā)中,數(shù)據(jù)庫里存的主鍵 ID 明明是:1750433246798835714,但是前端接收到數(shù)據(jù)后,ID 卻變成了:1750433246798835700,后幾位莫名其妙變成了 0!
導(dǎo)致的結(jié)果就是:
前端拿這個錯誤的 ID 去查詢詳情或執(zhí)行刪除操作時,后端直接報錯“數(shù)據(jù)不存在”,因為 ID 對不上。
原因分析
這個問題的根源在于 Java 和 JavaScript 對數(shù)字處理機(jī)制的不同。
Java 中的 Long 類型是 64 位有符號整數(shù),它的取值范圍非常大;
而常用的雪花算法 (Snowflake) 生成的 ID 通常就是 19 位的,完全在 Java 的 Long 范圍內(nèi)。
JavaScript 中并沒有專門的整數(shù)類型,所有的數(shù)字本質(zhì)上都是 IEEE 754 標(biāo)準(zhǔn)的雙精度浮點(diǎn)數(shù)(Double)。
JS 能安全表示的最大整數(shù)(Safe Integer)是253-1,這就導(dǎo)致后端的 19 位 ID傳給前端時,因為超過了 JS 的安全整數(shù)范圍,JS 就會發(fā)生精度丟失,自動進(jìn)行“四舍五入”或者直接丟棄低位,導(dǎo)致后幾位變成 0。
解決方案
要解決這個問題,最簡單有效的方法是:
后端在返回數(shù)據(jù)給前端時,把 Long 類型的數(shù)據(jù)統(tǒng)統(tǒng)轉(zhuǎn)換成 String(字符串)類型。
因為字符串在 JS 里是絕對安全的,不會發(fā)生精度丟失。
不需要手動去改每一個 DTO 或 VO 類,只需要在 Spring Boot 中加一個全局配置類,利用 Jackson 的序列化機(jī)制自動完成轉(zhuǎn)換。
直接在 config 包下新建一個類JsonConfig.java:
/**
* Spring MVC全局Json配置
* 用于解決 Long 類型精度丟失問題
*/
@JsonComponent
public class JsonConfig {
/**
* 全局配置:將 Long 類型序列化為 String
*/
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
// 創(chuàng)建 ObjectMapper
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 創(chuàng)建自定義序列化模塊
SimpleModule module = new SimpleModule();
// 將 Long 類(包裝類)和 long(基本類型)都序列化為字符串
// ToStringSerializer.instance 會調(diào)用對象的 toString() 方法
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
// 注冊模塊
objectMapper.registerModule(module);
return objectMapper;
}
}使用這種全局配置 方案,可以一勞永逸地解決項目中所有 Long 類型精度丟失的問題。
總結(jié)
到此這篇關(guān)于后端Long類型ID傳給前端精度丟失(變00)的原因分析及解決方案的文章就介紹到這了,更多相關(guān)后端Long類型傳前端精度丟失內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis學(xué)習(xí)教程(七)-Mybatis緩存介紹
MyBatis緩存分為一級緩存和二級緩存一級緩存,本文給大家介紹mybatis緩存知識,非常不錯具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
VScode 打造完美java開發(fā)環(huán)境最新教程
這篇文章主要介紹了VScode 打造完美java開發(fā)環(huán)境最新教程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12

