雪花算法ID在前端丢失精度解决方案
首先说一下背景,目前笔者的工作是物联网方面的,设备有对应的智慧运营平台,平台开发中建表的主键用的是Mybatis plus默认的雪花算法来生成的,也就是分布式系统比较常用的雪花ID,技术栈就是常用的Spring boot+Spring could Alibaba,json工具用的是FastJson。
在开发的过程中遇到了一个问题:前端接收到的数据在回传给后端的时候ID总是不对,仔细排查发现,前端接收到的数据的ID末尾两到三位数字都变成了0。雪花ID的长度是19位数字,系统在bean中的ID用的是Long类型,数据库建表用的是bigint,接收雪花ID自然没有问题,但是前端的number类型只能接收16位数字,准确的说是:2的53次方减1,即为9007199254740991,所以回传的ID不对是数字精度丢失的原因造成的。
知道了原因,解决方案也很简单,后端传给前端时把ID转换位字符串类型,前端接收字符串就不会丢失精度了,前端把ID回传给后端的时候,Spring的反序列化会自动为我们转成Long类型,这么一来就解决问题了。针对这一思路,楼主想到了两种解决方案。
1、@JsonSerialize注解
JsonSerialize注解可以帮我们实现字段值的序列化和反序列话,@JsonSerialize(using = ToStringSerializer.class),代码如下:
public class Device{
@ApiModelProperty(value = "物联终端id")
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long deviceId;
...
}
在需要解决数字过长的字段上添加sonSerialize注解就可以完美解决这一问题,但是开发的时候一定要注意,万一漏掉很容易踩坑,所以在员工培训的时候一定要有所交待。
2、过滤器
过滤器是一种一劳永逸的方法,笔者的项目引入的是fastjson依赖,fastjson可以通过SerializeFilters定制序列化,非常方便,先上代码:
package com.johanChan.app.config; import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter; import java.util.ArrayList;
import java.util.List; /**
* @author JohanChan
* @ProjectName Demo
* @Description 与前端交互时对实体类中Long类型的ID字段序列号
* @time 2021/6/23 11:30
*/
@Configuration
public class CustomFastJsonHttpMessageConverter {
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig(); List<SerializerFeature> list = new ArrayList<>();
list.add(SerializerFeature.PrettyFormat);
list.add(SerializerFeature.WriteMapNullValue);
list.add(SerializerFeature.WriteNullStringAsEmpty);
list.add(SerializerFeature.WriteNullListAsEmpty);
list.add(SerializerFeature.QuoteFieldNames);
list.add(SerializerFeature.WriteDateUseDateFormat);
list.add(SerializerFeature.DisableCircularReferenceDetect);
list.add(SerializerFeature.WriteBigDecimalAsPlain); fastJsonConfig.setSerializerFeatures(list.toArray(new SerializerFeature[list.size()])); fastConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastConverter;
fastJsonConfig.setSerializeFilters(new ValueFilter() {
@Override
public Object process(Object object, String name, Object value) {
/*if ((StringUtils.endsWith(name, "Id") || StringUtils.equals(name,"id")) && value != null
&& value.getClass() == Long.class) {*/
if (value != null && value.getClass() == Long.class ) {
Long v = (Long) value;
if (v.toString().length() > 15) {
return String.valueOf(value);
}
}
return value;
}
});
return new HttpMessageConverters(converter);
}
}
在ValueFilter中自定义规则,long类型的变量值如果超过15位数则转化成字符串,前端的number类型可以接收16位数字,为什么不用16位判断呢?前面已经说过,前端虽然可以接收16位的数字,但最大是9007199254740991,如果用16位做判断,就会有漏网之鱼了。这种方法省心省力,基本上开发人员不需要再注意这种数字过大的问题,但是使用的时候也要有所考量,根据实际业务考虑系统中有没有其他需求需要用较长的数字,统一用过滤器会不会受到影响。
雪花算法ID在前端丢失精度解决方案的更多相关文章
- 完美解决方案-雪花算法ID到前端之后精度丢失问题
最近公司的一个项目组要把以前的单体应用进行为服务拆分,表的ID主键使用Mybatis plus默认 的雪花算法来生成. 快下班的时候,小伙伴跑过来找我,:"快给我看看这问题,卡这卡了小半天了 ...
- Long类型转json时前端js丢失精度解决方案
一.问题背景 Java后端开发过程中,尤其是id字段,因数值太大,通过json形式传输到前端后,在js解析时,会丢失精度. 如果对精度丢失没有什么概念,可以看一个知乎的帖子,来感受一下:https:/ ...
- mybatis plus 主键生成 Twitter雪花算法 id 及修改id为字符型
mybatis plus配置主键生成策略为2,就是 使用Twitter雪花算法 生成id spring boot中配置为: GlobalConfiguration conf = new GlobalC ...
- JS 浮点数运算丢失精度解决方案
除法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].l ...
- 分布式ID的雪花算法及坑
分布式ID生成是目前系统的常见刚需,其中以Twitter的雪花算法(Snowflake)比较知名,有Java等各种语言的版本及各种改进版本,能生成满足分布式ID,返回ID为Long长整数 但是这里有一 ...
- 前端Long类型丢失精度问题
有时候后端向前端传输Long类型,数字过长会出现丢失精度的问题 比如后端传来的是这样一个长数字串 那么前端的弹窗显示的是 
Jenkins CI&CD 自动化发布项目实战(上篇) 作者 刘畅 时间 2020-11-28 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...
- Gym 100169E Tetrahedron Inequality
大致题意: 给出六条边,判断是否能组成四面体 分析: 四面体由四个三角形组成,所以每一条边肯定要符合三角形的任意两边大于第三边的性质.一开始以为这样判断就可以了,然而这题并没有这么简单. 如右图,有四 ...
- 浅读tomcat架构设计之Pipeline-Valve管道(4)
tomcat Container容器处理请求是使用Pipeline-Valve管道来处理的,后续写的tomcat内存马,和他紧密结合 Pipeline-Valve是责任链模式,责任链模式是指在一个请求 ...
- AcWing 1140. 最短网络
农夫约翰被选为他们镇的镇长! 他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场. 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场. 约翰的农场的编号是1,其他农场 ...
- css图片显示文字(上浮)
<html> <head lang="en"> <meta charset="UTF-8"> <title>&l ...
- rename 批量修改文件名
1.rename的用法 rename与mv的区别就是mv只能对单个文件重命名,而rename可以批量修改文件名 linux中的rename有两种版本,一种是C语言版的,一种是Perl版的.早期的Lin ...
- 深入理解Java容器——HashMap
目录 存储结构 初始化 put resize 树化 get 为什么equals和hashCode要同时重写? 为何HashMap的数组长度一定是2的次幂? 线程安全 参考 存储结构 JDK1.8前是数 ...
- 传统.NET 4.x应用容器化体验(1)
我们都知道.NET Core应用可以跑在Docker上,那.NET Framework 4.x应用呢?借助阿里云ECS主机(Windows Server 2019 with Container版本), ...
- TCP连接的11种状态
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议.TCP协议主要针对三次握手建立连接和四次挥手断开连接,其中包括了 ...
- Rust安装-运行第一个程序-hello_world
Rust官网:https://rust-lang.org/ 安装 点击install,选择版本 选择相对应的版本进行下载 我这里下载的是windows系统,运行下载好的exe文件,根据需要选择选对应的 ...