Java 解决long类型数据在前后端传递失真问题

news/2024/12/22 23:01:40/

最近项目从Mysql数据库换成了PostgressSQL导致以前用的很舒服的id自增不能用了,pgsql想自增还要创建序列比较麻烦,所以换成了UUID和雪花算法,因此遇到long类型id传递失真。

雪花算法生成的分布式ID长度为19位,前端JS接收数字能够达到的最大精度为16位,因此导致前端得到的ID不是真正的ID。

1、UUID

优点:对于所有的UUID它可以保证在时间和空间上的唯一性,它通过MAC地址,时间戳,命名空间,随机数,伪随机数来保证生成ID的唯一性,有着固定的大小(128bit)。它的唯一性和一致性特点使得可以无需注册过程就能够产生一个新的UUID。

缺点:UUID无序,且UUID在意外情况下(mac地址等其他生成UUID的因素相同的情况)可能会出现UUID相同,且存在隐私安全问题(mac地址)。

2、雪花算法SnowFlake

算法结构:符号位+时间戳+工作进程位+序列号位,一个64bit的整数,8字节,正好为一个long类型数据。

优点:所有生成的id按时间趋势递增,整个分布式系统内不会产生重复id。
缺点:由于雪花算法严重依赖时间,所以当发生服务器时钟回拨的问题是会导致可能产生重复的id。雪花算法的长度是19(long型最多19位)位的,前端能够接收的数字最多只能是16位的,因此就会造成精度丢失,得到的ID不是真正的ID。

解决方案

1、如果自身的项目可以修改id类型为String,那就用String类型代替

2、使用注解@JsonSerialize(using = ToStringSerializer.class),此方式的弊端就是要在每一个Entity类的字段上添加注解

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@Data
public class Person {

    /**
     * 方式二:JsonSerialize注解
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
}

3、在拦截器中加入Long类型转换

@Configuration
@EnableWebMvc
public class InterceptorConfig implements WebMvcConfigurer {
    /**
     * 方式三:拦截器转换
     */
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(0, jackson2HttpMessageConverter);
    }
}

4、ObjectMapper注入

@Configuration
public class JsonConfig{
    /**
     * 方式四:ObjectMapper注入
     */
    @Bean
    public ObjectMapper objectMapper (Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}

以上!


http://www.ppmy.cn/news/5242.html

相关文章

核心词根与重点单词

it走 exit [ˈeksɪt] ex&#xff08;出&#xff09;it&#xff08;走&#xff09;→ n.通道&#xff0c;出口There is a fire exit on each floor of the building. 这栋建筑每层楼都有个消防通道 initial [ɪˈnɪʃl] in&#xff08;里面&#xff09;it&#xff08;走&a…

关于多进程/多线程的一些问题

进程切换与线程切换的区别 进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间&#xff0c;而线程是共享所在进程的虚拟地址空间的&#xff0c;因此同一个进程中的线程进行线程切换时不涉及虚拟…

动态SQL 模糊查询 联表查询

1. 正文 1. set标签 和 foreach标签 trim标签 sql片段2. mybatis映射文件处理特殊字符.3. mybatis完成模糊查询。4. 联表查询 2. 动态sql2.1 set标签 这个配合if标签一起用&#xff0c;一般用在修改语句。如果传递的参数值为null&#xff0c;那么应该不修改该列的值。 <!-…

华为云APIArts:API全生命周期一体化解决方案,帮助您端到端呵护您的API

摘要&#xff1a;华为云API Arts是API设计、API开发、API测试、API托管、API运维、API变现一体化协作平台&#xff0c;通过维护API各开发阶段数据高度一致&#xff0c;支持开发者高效实现API全流程一站式体验。 伴随数字化浪潮的到来&#xff0c;应用编程接口(API)已经成为一个…

时间老去,Ruby不死,Ruby语言基础入门教程之Ruby3全平台开发环境搭建EP00

如果说电子游戏是第九艺术&#xff0c;那么&#xff0c;编程技术则配得上第十艺术的雅称。艺术发展的普遍规律就是要给与人们对于艺术作品的更高层感受&#xff0c;而Matz的Ruby语言则正是这样一件艺术品。 无论是语法还是理念&#xff0c;都让Ruby开发者感受到款待&#xff0…

【Django】第二课 银行账户管理系统开发

概念 本文在上一篇文章基础之前进行构建和完善 账户信息的分页显示 用户通过点击首页的“查询账户”&#xff0c;进入账户信息查询页面 则点击该按钮触发点击事件&#xff0c;向django服务器发出请求 接着我们在urls.py中需要定义与该地址进行匹配的地址&#xff0c;并匹配后…

【Python机器学习】神经网络中常用激活函数、损失函数、优化方法(图文解释 附源码)

下面以经典的分类任务&#xff1a;MNIST手写数字识别&#xff0c;采用全连接层神经网络 MNIST数据集是一个手写体的数字图片集&#xff0c;它包含有训练集和测试集&#xff0c;由250个人手写的数字构成。训练集包含60000个样本&#xff0c;测试集包含10000个样本。每个样本包括…

iOS的启动优化

应用的启动优化 当我们参与到大型应用的时候 会遇到一些启动时间过长的情况 这时候就需要使用到相关的操作。 总结来说&#xff0c;main()方法调用前&#xff0c;启动过程大体分为如下步骤&#xff1a; 先是LLVM把项目翻译成IR文件然后到backend LLVM clang pre-main main …