Long类型雪花算法ID返回前端后三位精度缺失问题解决

2023-10-31

一、问题描述

Java 后端使用雪花算法生成 Long 类型的主键 ID,在返回前端后,会出现后三位精度丢失的问题。

在这里插入图片描述

在这里插入图片描述

我们写一个 ControllerAdvice 打印一下返回结果看下:

在这里插入图片描述

我们可以看到返回结果是没有问题的,但是返回到前端就会丢失两位精度

二、问题复现

这里主要描述问题的复现过程和代码,不需要的可以直接跳过。

1.Maven依赖

<!-- Hutool,用于生成雪花算法ID -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>

<!-- Thymeleaf,用于展示页面 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2.application.yml 配置

server:
  port: 8080

spring:
  mvc:
    view:
      prefix: /templates/
      suffix: .html

3.DemoController.java

import cn.hutool.core.util.IdUtil;
import com.demo.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * <p> @Title DemoController
 * <p> @Description 测试Controller
 *
 * @author ACGkaka
 * @date 2023/4/24 18:02
 */
@Slf4j
@Controller
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/snowflakePage")
    public String snowflakePage() {
        return "snowflakePage";
    }

    @GetMapping("/snowflakeId")
    @ResponseBody
    public Result<Object> snowflakeId() {
        return Result.succeed().setData(IdUtil.getSnowflakeNextId());
    }
}

4.snowflakePage.html 页面

页面文件在 resources/templates/ 路径下。

在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
    <title>调用接口并打印返回值</title>
</head>
<body>
<button onclick="getSnowflakeId()">调用接口</button>
<script>
    function getSnowflakeId() {
        fetch('/demo/snowflakeId')
            .then(response => response.json())
            .then(data => {
                console.log(data.data);
                document.body.innerHTML += `<p>${data.data}</p>`;
            })
            .catch(error => console.log(error));
    }
</script>
</body>
</html>

5.DemoControllerAdvice.java 监听

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * <p> @Title DemoControllerAdvice
 * <p> @Description Controller增强
 *
 * @author ACGkaka
 * @date 2023/4/25 21:07
 */
@ControllerAdvice
public class DemoControllerAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        System.out.println("body is: " + body);
        return body;
    }
}

6.问题复现

请求地址:http://localhost:8080/demo/snowflakePage

在这里插入图片描述

在这里插入图片描述

精度丢失问题复现,下面我们来分析下导致问题的原因。

三、原因分析

  • 后端返回:1703327682407702528
  • 前端接收:1703327682407702500

这是因为 JS 是弱语言,前端接收数字类型参数为 number最大接受长度为 16 位超出长度则会丢失精度。而 JavaLong 类型长度是 19 位,所以传输到前端的后三位精度丢失。

解决问题的思路:把 Java 中 Long 类型转换为 String 类型返回给前端。

四、问题解决

方案一

将所有 ID 使用 String 类型存储,缺点是字符串做 ID 查询效率比较低

方案二

使用注解、配置类,改变序列化过程。

注解方式,适用于 pojo 的 id 属性上。

import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;

/**
 * 主键
 */
@TableId
@JsonSerialize(using = ToStringSerializer.class)
private Long id;

配置类方式,适用于全局配置。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfig {
  @Bean
  @Primary
  @ConditionalOnMissingBean(ObjectMapper.class)
  public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
  {
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    // 全局配置序修改列化返回 Json 处理方案
    SimpleModule simpleModule = new SimpleModule();
    // Json Long --> String
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    objectMapper.registerModule(simpleModule);
    return objectMapper;
  }
}

根据问题复现代码,再次请求地址:http://localhost:8080/demo/snowflakePage

在这里插入图片描述

在这里插入图片描述

精度丢失问题已修复。

整理完毕,完结撒花~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Long类型雪花算法ID返回前端后三位精度缺失问题解决 的相关文章

随机推荐

  • 开发板的上电锁存

    1 开发板的软启动 开发板的电源开关用两种 1 拨码开关 打到一侧则接通 打到另一侧则关闭 开发板只有关闭和运行两种状态 电路设计简单 但是不能实现休眠模式 低功耗模式 2 按键 按下时通电 弹起时断电 但是我们可以给供电电路增加置锁电路
  • windbg双机调试的连接设置和常见问题(真机和VMware虚拟机间的连接)

    一些废话 在做内核开发的时候 windbg给我们提供了方便 但是windbg要求内核调试是双机调试 所以我们首先面对的是调试机和被调试机的连接问题 相信大部分开发人员都是用实体机开发好代码 放到虚拟机中运行 并在实体机中运行windbg对虚
  • linux网络编程(五)epoll进阶

    文章目录 1 事件模型 1 1 ET模式 1 2 LT模式 1 3 比较 2 实例一 3 实例二 4 实例三 1 事件模型 EPOLL事件有两种模型 Edge Triggered ET 边缘触发只有数据到来才触发 不管缓存区中是否还有数据
  • ESP8266云端数据加密保护

    启用mosquitto上加密 要在mosquitto上启用加密 您首先需要拥有证书 您可以从发行证书的公司购买它们 也可以将它们自己生成为自签名证书 安装OpenSSL包 首先 确认您已安装openssl软件包 并且它具有较新的版本 1 0
  • MySQL中数据库重命名

    今天同事让帮忙把线上的数据库重命名 恩 数据库重命名 这种需求的概率小之又小 今天居然还真给碰到了 表重名的话是rename table old table to new table So 库的重命名最简单快捷的办法是 rename old
  • yolov7裁剪出识别结果

    开头先附上两篇有关yolov7的使用教程 yolov7保姆级教程 链接 yolov7数据增强与数据划分 链接 本篇主要内容为 在识别出来目标照片后 对目标进行裁剪 1 准备照片与标签 标签的生成在执行代码中加入 save txt 完整命令如
  • 雪花ID生成

    package com zfsw spzx access service import lombok extern slf4j Slf4j import org apache commons lang3 StringUtils import
  • 教师节到了,用Python做了个非常好用的学生点名系统

    教师节到了 用Python做了个非常好用的学生点名系统 教师节到了 祝伟大的老师们教师节快乐 前言 我的亲人和朋友里有很多老师 根据我的调查 现在的学生大部分都很积极 会主动举手回答问题 但是 也会遇到一些不好的情况 比如年级越高主动举手的
  • esp学习笔记一环境搭建

    文章目录 开发板资料 环境安装 编译程序 wsl终端 开发板资料 https docs espressif com projects esp idf zh CN latest get started get started devkitc
  • eladmin代码生成详细过程

    eladmin代码生成详细过程 笔记介绍 大家好 这里是千寻简笔记 我是作者星辰 笔记内容整理并发布 内容有误请指出 笔记源码已开源 前往Gitee搜索 chihiro notes 感谢您的观看 作者各大平台直链 GitHub Gitee
  • 基于Android网上在线学生选课系统

    老师要求 1 调研了解学生选课的流程 并做好需求分析 2 APP模式 3 设计角色 学生 工作人员等 4 工作人员管理课程信息 教师信息 学生信息 选课信息等 设置选课时间 选课班级等 5 学生登录 选课 查询成绩等 6 扩展功能 短信提示
  • windows scp下载较大文件出错

    在 ssh config中加入 Host 断开时重试连接的次数 ServerAliveCountMax 10 每隔30秒自动发送一个空的请求以保持连接 ServerAliveInterval 30 参考 https zhuanlan zhi
  • idea 2023.1设置:字体设置及自动调整大小

    一 原界面截图 二 修改字体设置 2 1 Font设置字体及大小 与下面相比 能调整字体和行高 2 2 鼠标滚轮调整字体大小 与上面相比 Ctrl 滑轮 只能调整字体大小 如果找不到 可直接搜 wheel 三 修改后界面截图 组合键在修改字
  • 《算法二》选择排序算法及它的时间复杂度

    1 选择排序算法 选择排序算法的时间复杂度为O N 2 选择排序算法规则 1 指定位置的数和后面的数比较 2 如果指定位置的数大 则两个数交换位置 3 向后移动一个位置 和指定位置的数进行比较 假设数组大小 n 第一轮比较n 1次 最小的数
  • 【如何训练一个中英翻译模型】LSTM机器翻译模型部署之ncnn(python)(五)

    系列文章 如何训练一个中英翻译模型 LSTM机器翻译seq2seq字符编码 一 如何训练一个中英翻译模型 LSTM机器翻译模型训练与保存 二 如何训练一个中英翻译模型 LSTM机器翻译模型部署 三 如何训练一个中英翻译模型 LSTM机器翻译
  • Pytorch 基础之张量合并与分割

    本次介绍一下 Tensor 张量合并与分割常用的一些方法 1 torch cat tensors dim 0 out None Tensor 方法释义 对除了要合并维度之外 其它维度 shape 都一样的 tensor 序列 数组或列表 进
  • 新手学习须注意的问题

    注意事项 1 最新版本的MDK软件Keil的编译器版本已更新到v6 且与v5版本不兼容 之前老的项目编译使用v6版编译器都会出错 建议使用老版本的Keil 如v5 36等 单纯安装v5版本的编译器比较麻烦 Keil v536同时自带v5 v
  • linux用rdate命令实现同步时间

    author skate time 2010 05 07 用rdate命令实现同步时间 前两天说到用ntp时间服务器和ntpdate命令同步时间 今天简单记录下用rdate同步时间 http blog csdn net wyzxg arch
  • Webplus网站群管理平台介绍

    简介 Webplus网站群管理平台采用模块化设计 无需用户编程 便可轻松规划 建设一个或多个功能强大的动态信息门户网站 可以同时建立多个信息相关联的网站 所有网站制作和管理均基于统一的身份认证 简单而实用的流程管理 可以做到单个网站的多部门
  • Long类型雪花算法ID返回前端后三位精度缺失问题解决

    目录 一 问题描述 二 问题复现 1 Maven依赖 2 application yml 配置 3 DemoController java 4 snowflakePage html 页面 5 DemoControllerAdvice jav