<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文用範例介紹SpringBoot如何解決雪花演演算法主鍵ID傳到前端後精度丟失問題。
Java後端Long型別的範圍
前端JS的數位型別的範圍
結論
可見,Java後端的Long寬度大於前端的。雪花演演算法一般會生成18位元或者19位寬度的數位,那麼這時就會出問題。
1.表結構
主鍵型別是BIGINT,儲存雪花演演算法生成的ID。
CREATE TABLE `user` ( `id` BIGINT(32) NOT NULL COMMENT '使用者id', ... PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='使用者表';
2.Entity
用Long 型別對應資料庫ID的BIGINT型別。
這裡使用 MybatisPlus 的雪花演演算法自動生成19位長度的純數位作為主鍵ID。(當然也可以手動用雪花演演算法生成ID)
import lombok.Data; @Data public class User { @TableId(type = IdType.ASSIGN_ID) private Long id; //其他成員 }
3.響應給前端
以JSON資料響應給前端正常
{ "id": 1352166380631257089, ... }
範例
Controller
package com.knife.controller; import com.knife.entity.UserVO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("user") public class UserController { @GetMapping("find") public UserVO find(Long id) { UserVO userVO = new UserVO(); userVO.setId(id); userVO.setUsername("Tony"); return userVO; } }
Entity
package com.knife.entity; import lombok.Data; @Data public class UserVO { private Long id; private String username; }
測試
存取:http://localhost:8080/user/find?id=1352213368413982722
結果
從上邊可以看到,並沒有問題。
為什麼沒有出問題?
前端傳入後端:SpingMVC會自動將String型別的ID轉為Long型別,不會出問題後端響應給前端:是JSON格式,與JS沒有關係,不會出問題
什麼時候會出問題?
前端接收到JSON之後,將其序列化為JS物件,然後進行其他操作。在JSON轉JS物件時就會出問題,如下:
可以看到,原來id為1352213368413982722,序列化為JS物件後變成了 1352213368413982700
程式碼為:
const json = '{"id": 1352213368413982722, "name": "Tony"}'; const obj = JSON.parse(json); console.log(obj.id); console.log(obj.name);
有如下兩種方案
方案1使用String 型別做資料庫ID,查詢效能會大幅度下降。所以應該採用方案2。本文介紹方案2。
簡介
自定義ObjectMapper。
方案1:ToStringSerializer(推薦)
package com.knife.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { @Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 全域性設定序列化返回 JSON 處理 SimpleModule simpleModule = new SimpleModule(); // 將使用String來序列化Long型別 simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(simpleModule); return objectMapper; } }
測試
存取:http://localhost:8080/user/find?id=1352213368413982722
方案2:自定義序列化器(不推薦)
序列化器
package com.knife.config; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; import com.fasterxml.jackson.databind.ser.std.NumberSerializer; import java.io.IOException; /** * 超出 JS 最大最小值 處理 */ @JacksonStdImpl public class BigNumberSerializer extends NumberSerializer { /** * 根據 JS Number.MAX_SAFE_INTEGER 與 Number.MIN_SAFE_INTEGER 得來 */ private static final long MAX_SAFE_INTEGER = 9007199254740991L; private static final long MIN_SAFE_INTEGER = -9007199254740991L; /** * 提供範例 */ public static final BigNumberSerializer instance = new BigNumberSerializer(Number.class); public BigNumberSerializer(Class<? extends Number> rawType) { super(rawType); } @Override public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { // 超出範圍 序列化位字串 if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { super.serialize(value, gen, provider); } else { gen.writeString(value.toString()); } } }
ObjectMapper設定
package com.knife.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; @Configuration public class JacksonConfig { @Bean public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 全域性設定序列化返回 JSON 處理 SimpleModule simpleModule = new SimpleModule(); // 將使用自定義序列化器來序列化Long型別 simpleModule.addSerializer(Long.class, BigNumberSerializer.instance); simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.instance); objectMapper.registerModule(simpleModule); return objectMapper; } }
測試
存取:http://localhost:8080/user/find?id=1352213368413982722
說明
在欄位上加:@JsonSerialize(using= ToStringSerializer.class)。
範例
package com.knife.entity; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; @Data public class UserVO { @JsonSerialize(using= ToStringSerializer.class) private Long id; private String username; }
測試
存取:http://localhost:8080/user/find?id=1352213368413982722
到此這篇關於SpringBoot雪花演演算法主鍵ID傳到前端後精度丟失問題的解決的文章就介紹到這了,更多相關SpringBoot雪花演演算法主鍵ID精度丟失內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45