当前位置: 首页 > article >正文

Long类型的数据在网络传输的过程中丢失精度

文章目录

  • 1. 准备工作
    • 1.1 导入测试工程
    • 1.2 运行SQL脚本
    • 1.3 修改与连接数据库相关的信息
  • 2. 问题呈现
  • 3. 问题产生的原因
  • 4. 解决方法(利用JSON序列化和反序列化)
    • 4.1 特殊标识(自定义注解)
    • 4.2 关键类
    • 4.3 在id字段上添加自定义注解
    • 4.4 成功解决
  • 5. 添加JSON序列化和反序列化后与Date类型相关的注意事项

视频教程:黑马程序员Java项目实战微服务项目《黑马头条》开发全套视频教程,基于SpringBoot+SpringCloud+Nacos等企业级微服务架构项目解决方案

1. 准备工作

1.1 导入测试工程

为了复现问题,我们先导入测试工程,测试工程的 Gitee 地址:long-type-precision-loss-problem

1.2 运行SQL脚本

SQL 脚本在测试工程的 sql 目录下

在这里插入图片描述

1.3 修改与连接数据库相关的信息

application.yml

在这里插入图片描述

2. 问题呈现

启动测试工程后,在浏览器访问项目

http://localhost:12100/

在这里插入图片描述

我们拿第一条文章的 ID 到数据库中进行查询,发现没有结果

select *
from ap_article
where id = 1383827787629252600;

这是为什么呢,明明文章的 id 是后端返回的,为什么用后端返回的文章 id 却查不到文章的信息呢

3. 问题产生的原因

我们换成根据文章标题查询,却发现能查询出对应的文章

select *
from ap_article
where title = 'Kafka文件的存储机制';

在这里插入图片描述

这是为什么呢

我们对比一下数据库返回的文章 id 和前端显示的文章 id,可以发现两个 id 的末尾部分不一致(白底的是前端显示的,黑底的是数据库返回的)

在这里插入图片描述

而且 id 列的每一个数据末尾部分都是 00

在这里插入图片描述

问题产生的原因就是 Long 类型的数据在进行网络传输的时候,精度丢失了

4. 解决方法(利用JSON序列化和反序列化)

我们可以利用 JSON 序列化和反序列化来解决 Long类型的数据在网络传输的过程中丢失精度的问题


以下是整体思路

  • 当后端响应给前端的数据中包含了 id 或者特殊标识(自定义)的时候,把当前数据进行转换为 String 类型
  • 当前端传递给后端的 dto 中有 id 或者特殊标识(自定义)的时候,把当前数据转为 Integer 或 Long 类型

4.1 特殊标识(自定义注解)

那如何标记某个字段是否需要进行序列化和反序列化呢

我们可以通过自定义注解实现,如果某个字段需要进行序列化和反序列化,就为该字段添加自定义注解

import com.fasterxml.jackson.annotation.JacksonAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@JacksonAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface IdEncrypt {
    
}

4.2 关键类

关键的几个类放在了 jackson 包下

在这里插入图片描述

几个类的功能如下:

类名功能描述
ConfusionSerializer自定义序列化器,用于序列化时处理自增数字的混淆,将非空值转换为字符串并写入JSON
ConfusionDeserializer自定义反序列化器,用于反序列化时处理自增数字的混淆解密,根据字段类型进行相应的解析
ConfusionSerializerModifier序列化修改器,用于过滤和修改序列化过程中处理的字段,为需要混淆的字段分配自定义序列化器
ConfusionDeserializerModifier反序列化修改器,用于过滤和修改反序列化过程中处理的字段,为需要解密的字段分配自定义反序列化器
ConfusionModuleJackson模块,用于注册自定义的序列化和反序列化修改器,配置ObjectMapper的全局特性
InitJacksonConfigSpring配置类,提供自动化的ObjectMapper配置,注册ConfusionModule,使框架自动处理ID混淆

只要某个字段上有自定义注解或者字段的名字为 id,就会自动完成序列化和反序列化的操作

在这里插入图片描述

import cn.edu.scau.enums.IdEncrypt;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;

import java.util.Iterator;

public class ConfusionDeserializerModifier extends BeanDeserializerModifier {

    @Override
    public BeanDeserializerBuilder updateBuilder(final DeserializationConfig config, final BeanDescription beanDescription, final BeanDeserializerBuilder builder) {
        Iterator<SettableBeanProperty> it = builder.getProperties();

        while (it.hasNext()) {
            SettableBeanProperty settableBeanProperty = it.next();
            if ((null != settableBeanProperty.getAnnotation(IdEncrypt.class) || settableBeanProperty.getName().equalsIgnoreCase("id"))) {
                builder.addOrReplaceProperty(settableBeanProperty.withValueDeserializer(new ConfusionDeserializer(settableBeanProperty.getValueDeserializer(), settableBeanProperty.getType())), true);
            }
        }
        return builder;
    }

}

4.3 在id字段上添加自定义注解

@IdEncrypt

在这里插入图片描述

4.4 成功解决

完成上述配置后,重启项目,可以看到前端显示 id 列时已经没有精度丢失的问题了

我们随机挑选一个 id,到数据库中进行查询,发现也能查询到对应的文章

select *
from ap_article
where id = 1383827787629252610;

在这里插入图片描述

5. 添加JSON序列化和反序列化后与Date类型相关的注意事项

添加了 JSON 序列化和反序列化之后,Date 类型的数据返回给前端时会转换成时间戳


添加 JSON 序列化和反序列化之前

在这里插入图片描述


添加 JSON 序列化和反序列化之后

在这里插入图片描述

如果不想让 Date 类型的数据返回给前端时转换成时间戳,可以忽略对 Date 类型的转换

在这里插入图片描述

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

http://www.kler.cn/a/442886.html

相关文章:

  • 单细胞组学大模型(8)--- scGenePT,scGPT和GenePT的结合,实验数据和文本数据的交融模型
  • 记录一次电脑被入侵用来挖矿的过程(Trojan、Miner、Hack、turminoob)
  • 时序数据库InfluxDB—介绍与性能测试
  • Notepad++上NppFTP插件的安装和使用教程
  • Python-基于Pygame的小游戏(滑雪大冒险)(一)
  • 社交电商新风口:短视频交友+自营商城源码运营
  • filecoin boost GraphQL API 查询
  • AI开发 - 用GPT写一个GPT应用的真实案例
  • 在 Webpack 中Plugin有什么作用?Plugin是什么?
  • 华为认证HCIA——数据传输形式,数据封装的基本概念
  • 企业为什么会需要高防IP?
  • Elasticsearch:什么是信息检索?
  • 16.初识接口2.0 C#
  • SSM 电脑配件销售系统设计及 JSP 实现策略详解
  • 代码随想录算法训练营第八天-字符串-344. 反转字符串
  • OpenCV中的识别图片颜色并绘制轮廓
  • 深度解析:推荐系统的进化之路与深度学习革命
  • vue3中的v-model如何自定义修饰符
  • 科技的成就(六十六)
  • 快捷工具网(www.onlinetool7.com)提供Android KeyCode对照表,帮助开发者轻松理解按键事件
  • uniapp中的uni-file-picker组件上传多张图片到服务器
  • C++ Qt 模板函数和函数重载
  • 1.Nuxt学习 搭建项目 渲染页面基本操作
  • RabbitMQ的核心组件有哪些?