最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot主鍵ID傳到前端后精度丟失的問題解決

 更新時間:2022年05月23日 10:54:25   作者:IT利刃出鞘  
這篇文章主要通過示例為大家詳細介紹一些SpringBoot如何解決雪花算法主鍵ID傳到前端后精度丟失問題,文中的示例代碼講解詳細,需要的可以參考一下

簡介

本文用示例介紹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。

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.將數據庫表設計的id字段由 Long 類型改成 String 類型。

2.前端用String類型來保存ID保持精度,后端及數據庫繼續(xù)使用Long(BigINT)類型

方案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精度丟失內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring Boot命令行啟動添加參數的三種方式

    Spring Boot命令行啟動添加參數的三種方式

    在命令行中,常見的參數可以分為三類:選項參數、非選項參數和系統參數,本文就來介紹一下Spring Boot命令行三種參數形式,感興趣的可以了解一下
    2023-09-09
  • Nacos后臺頻繁打印get changedGroupKeys:[]的問題及解決

    Nacos后臺頻繁打印get changedGroupKeys:[]的問題及解決

    這篇文章主要介紹了Nacos后臺頻繁打印get changedGroupKeys:[]的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot 自動掃描第三方包及spring.factories失效的問題解決

    SpringBoot 自動掃描第三方包及spring.factories失效的問題解決

    這篇文章主要介紹了SpringBoot 自動掃描第三方包及spring.factories失效的問題,本文給大家分享最新解決方法,需要的朋友可以參考下
    2023-05-05
  • Java分支結構和循環(huán)結構原理與用法詳解

    Java分支結構和循環(huán)結構原理與用法詳解

    這篇文章主要介紹了Java分支結構和循環(huán)結構原理與用法,結合實例形式分析了java分支結構、循環(huán)結構、跳轉語句等相關概念、原理、使用技巧與操作注意事項,需要的朋友可以參考下
    2020-02-02
  • 關于SpringGateway調用服務 接受不到參數問題

    關于SpringGateway調用服務 接受不到參數問題

    這篇文章主要介紹了關于SpringGateway調用服務接受不到參數問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Springboot整合camunda+mysql的集成流程分析

    Springboot整合camunda+mysql的集成流程分析

    本文介紹基于mysql數據庫,如何實現camunda與springboot的集成,如何實現基于springboot運行camunda開源流程引擎,本文分步驟圖文相結合給大家介紹的非常詳細,需要的朋友參考下吧
    2021-06-06
  • java static塊和構造函數的實例詳解

    java static塊和構造函數的實例詳解

    這篇文章主要介紹了java static塊和構造函數的實例詳解的相關資料,希望通過本文能幫助到大家,讓大家理解掌握Java static關鍵字的函數方法,需要的朋友可以參考下
    2017-09-09
  • Java的正則表達式深入分析

    Java的正則表達式深入分析

    本篇文章介紹了,Java的正則表達式深入分析。需要的朋友參考下
    2013-04-04
  • Spring Boot事務配置操作

    Spring Boot事務配置操作

    這篇文章主要介紹了Spring Boot事務配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Springboot+redis+Interceptor+自定義annotation實現接口自動冪等

    Springboot+redis+Interceptor+自定義annotation實現接口自動冪等

    本篇文章給大家介紹了使用springboot和攔截器、redis來優(yōu)雅的實現接口冪等,對于冪等在實際的開發(fā)過程中是十分重要的,因為一個接口可能會被無數的客戶端調用,如何保證其不影響后臺的業(yè)務處理,如何保證其只影響數據一次是非常重要的,感興趣的朋友跟隨小編一起看看吧
    2019-07-07

最新評論

神木县| 阿拉善右旗| 益阳市| 黔江区| 舞阳县| 辉县市| 白城市| 宝兴县| 交城县| 江华| 汉川市| 阳原县| 榆树市| 河东区| 政和县| 图木舒克市| 宝清县| 黄大仙区| 原阳县| 阿鲁科尔沁旗| 河北区| 白沙| 潜江市| 竹山县| 神农架林区| 师宗县| 阿合奇县| 育儿| 敦化市| 山阳县| 潢川县| 石林| 自贡市| 德惠市| 上高县| 永兴县| 六枝特区| 衢州市| 马关县| 白河县| 静海县|