SpringBoot项目接口返回值中Long类型超过17位导致前端js在调用时出现丢失精度问题

原因

这是因为Javascript中数字的精度是有限的,bigint类型的的数字超出了Javascript的处理范围。JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。其结构如图
在这里插入图片描述

各位的含义如下:

  • 1位(s) 用来表示符号位
  • 11位(e) 用来表示指数
  • 52位(f) 表示尾数
    尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即 9007199254740992。而Bigint类型的有效位数是63位(扣除一位符号位),其最大值为:Math.pow(2,63)。任何大于 9007199254740992 的就可能会丢失精度:
19007199254740992     >> 10000000000000...000 // 共计 53 个 0
29007199254740992 + 1 >> 10000000000000...001 // 中间 52 个 0
39007199254740992 + 2 >> 10000000000000...010 // 中间 51 个 0

实际上值却是:

19007199254740992 + 1 // 丢失
29007199254740992 + 2 // 未丢失
39007199254740992 + 3 // 丢失
49007199254740992 + 4 // 未丢失

解决办法

解决办法很简单将Long类型的字段转为String类型返给前端即可,解决方法有4种可根据自己项目情况来选择:

方式1

在实体类种直接将Long类型的字段修改为String类型

方式2

在要返回的字段上添加@JsonSerialize(using = ToStringSerializer.class)注解,这样就能在序列化时自动将该字段类型转为String类型返给前端,相较于方式1不影响其他调用该字段的方法

方式3

通过配置全局拦截器将所有返回结果的Long类型字段转为String类型,代码如下:

@EnableWebMvc
@Configuration
public class WebDataConvertConfig implements WebMvcConfigurer {

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 序列换成json时,将所有的long变成string
     * 因为js中得数字类型不能包含所有的java long值
     */
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
    simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

    objectMapper.registerModule(simpleModule);
    // 设置为空的字段不返回
    objectMapper.setSerializationInclusion(NON_NULL);
    // 指定json转换时间类型的时区
    objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
    // 指定返回的时间格式
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    jackson2HttpMessageConverter.setObjectMapper(objectMapper);
    converters.add(jackson2HttpMessageConverter);
  }
}

方式四

配置参数:在ymlproperties中增加配置,参考博客

spring:
  jackson:
    generator:
      write_numbers_as_strings: true
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Springboot 项目前端页面可以通过 AJAX 或者直接调用后端接口的方式来调用后端的方法。 1. AJAX 调用方法 在前端页面使用 JavaScript 代码,通过 AJAX 技术发起 HTTP 请求,调用后端的方法。以下是一个简单的示例: ``` $.ajax({ url: "/hello", type: "GET", dataType: "text", success: function (result) { alert(result); }, error: function (xhr, status, error) { console.log(xhr.responseText); } }); ``` 上面的代码通过 jQuery 的 ajax 方法发起一个 GET 请求,请求后端的 /hello 接口。请求成功后,会弹出一个对话框显示返回的结果。 2. 直接调用后端接口方法 在前端页面,也可以通过直接调用后端的接口方法来实现方法调用。需要在前端页面引入后端接口的 JavaScript 文件,然后调用的方法即可。 以下是一个示例: ``` <script src="/js/hello.js"></script> <script> function sayHello() { var result = hello.sayHello("world"); alert(result); } </script> <button onclick="sayHello()">Say Hello</button> ``` 上面的代码引入了一个名为 hello.js 的 JavaScript 文件,在其定义了一个名为 sayHello 的方法。在前端页面,通过调用这个方法来实现后端方法的调用。当用户点击 Say Hello 按钮,会弹出一个对话框显示返回的结果。 需要注意的是,在使用这种方式调用后端方法,需要将后端接口的方法暴露为 JavaScript 方法,即在后端的 Controller 类使用 @ResponseBody 注解将返回值转换为 JSON 格式返回给前端。例如: ``` @RestController public class HelloController { @GetMapping("/hello") public String sayHello() { return "Hello, world!"; } } ``` 在上面的代码,使用 @RestController 注解标注了一个 Controller 类,并定义了一个名为 sayHello 的方法。当用户访问 /hello 接口,该方法会被调用,并将返回值转换为 JSON 格式返回给前端

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值