首先说一下背景,目前笔者的工作是物联网方面的,设备有对应的智慧运营平台,平台开发中建表的主键用的是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在前端丢失精度解决方案的更多相关文章

  1. 完美解决方案-雪花算法ID到前端之后精度丢失问题

    最近公司的一个项目组要把以前的单体应用进行为服务拆分,表的ID主键使用Mybatis plus默认 的雪花算法来生成. 快下班的时候,小伙伴跑过来找我,:"快给我看看这问题,卡这卡了小半天了 ...

  2. Long类型转json时前端js丢失精度解决方案

    一.问题背景 Java后端开发过程中,尤其是id字段,因数值太大,通过json形式传输到前端后,在js解析时,会丢失精度. 如果对精度丢失没有什么概念,可以看一个知乎的帖子,来感受一下:https:/ ...

  3. mybatis plus 主键生成 Twitter雪花算法 id 及修改id为字符型

    mybatis plus配置主键生成策略为2,就是 使用Twitter雪花算法 生成id spring boot中配置为: GlobalConfiguration conf = new GlobalC ...

  4. JS 浮点数运算丢失精度解决方案

    除法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].l ...

  5. 分布式ID的雪花算法及坑

    分布式ID生成是目前系统的常见刚需,其中以Twitter的雪花算法(Snowflake)比较知名,有Java等各种语言的版本及各种改进版本,能生成满足分布式ID,返回ID为Long长整数 但是这里有一 ...

  6. 前端Long类型丢失精度问题

    有时候后端向前端传输Long类型,数字过长会出现丢失精度的问题 比如后端传来的是这样一个长数字串 那么前端的弹窗显示的是 ![](https://img2022.cnblogs.com/blog/22 ...

  7. 第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现

    目录 2.3 分布式ID 2.3.1 功能概述 2.3.2 应用场景 2.3.3 使用说明 2.3.4 项目截图 2.3.5 Snowflake雪花算法的代码实现 2.3 分布式ID 2.3.1 功能 ...

  8. Long类型参数传到前端精度丢失的解决方案

        由于公司数据库表的id是利用雪花算法生成的,所以实体类里面定义的数据类型为Long.但是这个数据传到前端时,发生了精度丢失的现象.本文记录了从java后端的角度如何解决这个精度丢失的问题,便于 ...

  9. 使用雪花算法为分布式下全局ID、订单号等简单解决方案考虑到时钟回拨

    1.snowflake简介         互联网快速发展的今天,分布式应用系统已经见怪不怪,在分布式系统中,我们需要各种各样的ID,既然是ID那么必然是要保证全局唯一,除此之外,不同当业务还需要不同 ...

随机推荐

  1. 15 自动发布Java项目(Tomcat)

    #!/bin/bash export PAHT=/usr/local/maven/bin:/usr/local/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/ ...

  2. js实现页面下拉,区块(文字,图片等)左右淡入淡出效果

    html: <div class="box"> <span class="historybox"> </span> < ...

  3. mac sudo: /etc/sudoers is world writable

    今天误操作修改了/etc/sudoers的权限,将它的权限改成了777,结果就导致执行所有sudo的命令都报错. sudo: /etc/sudoers is world writable sudo: ...

  4. ubuntu16.04上编译android的可执行文件并调用本地so库

    前言: 找了蛮多资料的,发现目前实现的编译方式大致就两种,一种是直接使用android源码中的编译工具链,另一种就是使用独立的交叉编译工具链,第二种我还在实现中,配置步骤挺多的 ,第一种实现方式挺方便 ...

  5. spring boot框架相关知识

    1.spring:一个轻量级的控制反转和面向切面的容器,专业的开发Web项目的开源框架.    spring mvc:是基于spring的mvc框架,属于一个企业WEB开发的MVC框架,涵盖面包括前端 ...

  6. Java基础——自己的总结

    Java Java是什么? Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征.Java语言作 ...

  7. create-react-app 入门学习

    全局安装 create-react-app npm install create-react-app -g 创建项目 在全局安装了create-react-app 后 创建项目,如果按照下面的第一种办 ...

  8. 【网络IO系列】 预备知识 操作系统之内核程序和用户程序

    一.概念 首先我们先来复习一下操作系统的概念和作用 操作系统是用户和硬件之间的一层媒介程序,为上提供编程接口,为下调用资源,管理驱动,以使用硬件. 从以上的表述我们可以看出OS的两点作用,第一个是对下 ...

  9. File类与常用IO流第九章——转换流

    第九章.转换流 字节编码和字符集 编码:按照某种规则将字符以二进制存储到计算机中. 解码:将存储在计算机中的二进制数按照某种规则解析显示出来. 字符编码:Character Encoding ,就是一 ...

  10. Python基础之动态添加属性,方法,动态类,静态类

    ## 动态添加属性class Person: def __init__(self,name): self.name = name# 1.通过对象.属性名称来操作p = Person('KTModel' ...