JAVA中关于Long类型返回前端精度丢失问题处理办法

 更新时间:2024年11月27日 10:04:32   作者:昀贝  
这篇文章主要介绍了后端JavaBean的id属性从Long类型改为雪花算法后出现的精度丢失问题,解决方案包括将id字段类型改为字符串或使用Jackson序列化方式,需要的朋友可以参考下

问题出现:

新项目将后端的Java Bean的id属性是用的Long类型对应数据库主键使用bigint类型,id改为雪花后出现的异常问题,比如id:1799633456368132098返回错误的id:1799633456368132000。导致明显问题数值精度丢失。后三位数值转换为0了。

问题原因:

Java中的long能表示的范围比js中number大,也就意味着部分数值在js中存不下(变成不准确的值),导致Id最后几位直接变成了0。

解决方案一

1、将后端id字段类型换位字符串类型,并且前端以字符串的方式接收就不会有精度丢失了。

2、单个字段注释,这只需要我们在需要转换的字段上增加@JsonSerialize(using=ToStringSerializer.class)注解

解决方案二

SpringBoot使用Jackson序列化方式

需要引入依赖
<dependency>
		<groupId>com.fasterxml.jackson.datatype</groupId>
		<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
package com.znkj.nvm.common.config;

import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

/**
 * jackson 配置
 * 加载顺序:-10000
 **/
@Slf4j
@Order(-10000)
@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer customizer() {
        return builder -> {
            // 全局配置序列化返回 JSON 处理
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
            javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
            javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
            javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
            builder.modules(javaTimeModule);
            builder.timeZone(TimeZone.getDefault());
            log.info("初始化 jackson 配置");
        };
    }
}
package com.gyq.common.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.ser.std.NumberSerializer;
import java.io.IOException;

/**
 * 超出 JS 最大最小值 处理
 **/
@JacksonStdImpl
public class BigNumberSerializer extends NumberSerializer {

    /**
     * 根据 JS Number.MAX_SAFE_INTEGER 与 Number.MIN_SAFE_INTEGER 得来
     */
    private static final long MAX_SAFE_INTEGER = 9007199254740991L;
    private static final long MIN_SAFE_INTEGER = -9007199254740991L;

    /**
     * 提供实例
     */
    public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);

    public BigNumberSerializer(Class<? extends Number> rawType) {
        super(rawType);
    }

    @Override
    public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        // 超出范围 序列化位字符串
        if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
            super.serialize(value, gen, provider);
        } else {
            gen.writeString(value.toString());
        }
    }

}

总结 

到此这篇关于JAVA中关于Long类型返回前端精度丢失问题处理办法的文章就介绍到这了,更多相关JAVA Long类型返回前端精度丢失内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解java生成json字符串的方法

    详解java生成json字符串的方法

    本篇文章主要介绍了java生成json字符串的方法,包括map对象转换成json对象,list转换成json,json转换成list和map,有兴趣的可以了解一下。
    2017-01-01
  • Java 按照字节来截取字符串的代码(不会出现半个汉字)

    Java 按照字节来截取字符串的代码(不会出现半个汉字)

    Java 按照字节来截取字符串的工具,不会出现半个汉字。一个中文两个字节,一个英文字符只占 1 个字节** 1. 通常我们用于前端显示的时候,防止标题过长
    2014-01-01
  • Spring boot集成Go-FastDFS实现图片上传删除等功能实现

    Spring boot集成Go-FastDFS实现图片上传删除等功能实现

    这篇文章主要介绍了Spring boot集成Go-FastDFS实现图片上传删除等功能实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • SpringBoot整合Mail发送邮件功能

    SpringBoot整合Mail发送邮件功能

    我们在网站上注册账号的时候一般需要获取验证码,而这个验证码一般发送在你的手机号上还有的是发送在你的邮箱中,注册,账号密码…都需要用到验证,今天就演示一下如何用SpringBoot整合Mail发送邮箱
    2021-11-11
  • Spring Security 基于URL的权限判断源码解析

    Spring Security 基于URL的权限判断源码解析

    这篇文章主要介绍了Spring Security 基于URL的权限判断问题,我们想要实现自己的基于请求Url的授权只需自定义一个 AccessDecisionManager即可,接下来跟随小编一起看看实现代码吧
    2021-12-12
  • java多线程数据分页处理实例讲解

    java多线程数据分页处理实例讲解

    在本篇内容里小编给大家分享了一篇关于java多线程数据分页处理实例讲解内容,有兴趣的朋友们可以学习下。
    2021-01-01
  • SpringBoot整合Kaptcha实现图片验证码加减乘除功能

    SpringBoot整合Kaptcha实现图片验证码加减乘除功能

    在开发Web应用时,验证码是一个常见的功能,它可以帮助我们防止机器人的恶意操作,今天我们将学习如何使用Kaptcha生成图片验证码,并自定义验证码内容为100以内的加减乘除运算,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • Spring6 的JdbcTemplate的JDBC模板类的使用介绍(最新推荐)

    Spring6 的JdbcTemplate的JDBC模板类的使用介绍(最新推荐)

    JdbcTemplate 是Spring 提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码,当然,你也可以不用,可以让Spring集成其它的ORM框架,这篇文章主要介绍了Spring6 的JdbcTemplate的JDBC模板类的详细使用说明,需要的朋友可以参考下
    2024-05-05
  • java中stream的peek()用法详解

    java中stream的peek()用法详解

    这篇文章主要介绍了java中stream的peek()用法详解,peek的作用是
    改变元素的内部状态,对每个object执行 saveInfomation(object, params),然后把结果收集到一个 List 里,这里涉及到了最终操作,需要的朋友可以参考下
    2024-01-01
  • java编程基础之模仿用户登录代码分享

    java编程基础之模仿用户登录代码分享

    这篇文章主要介绍了java编程基础之模仿用户登录代码分享,小编觉得挺不错的,这里分享给大家,供需要的朋友参考。
    2017-10-10

最新评论