所有分类
  • 所有分类
  • 未分类

SpringBoot-解决雪花算法主键ID传到前端后精度丢失问题

简介

本文用示例介绍SpringBoot如何解决雪花算法主键ID传到前端后精度丢失问题。

项目场景

1.表结构

主键类型是BIGINT,存储雪花算法生成的ID。

CREATE TABLE `user` (
  `id` BIGINT(32) NOT NULL COMMENT '用户id',
	...
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

2.Entity

用Long 类型对应数据库ID的BIGINT类型。

这里使用 MybatisPlus 的雪花算法自动生成19位长度的纯数字作为主键ID。(当然也可以手动用雪花算法生成ID)

import lombok.Data;
 
@Data
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
	
    //其他成员
}

3.响应给前端

以JSON数据响应给前端正常

{
  "id": 1352166380631257089,
   ...
}

问题复现

代码

Controller

package com.knife.example.business.product.controller;

import com.knife.example.business.product.vo.ProductVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

@Api(tags = "商品")
@RestController
@RequestMapping("product")
public class ProductController {

    @ApiOperation("查询")
    @GetMapping("query")
    public ProductVO query(Long id) {

        //省略查数据库等逻辑。
        //为了简便,直接虚构一个vo
        ProductVO productVO = new ProductVO();
        productVO.setId(id);
        productVO.setName("鼠标");

        return productVO;
    }
}

VO

package com.knife.example.business.product.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@ApiModel("商品响应类")
public class ProductVO {
    @ApiModelProperty("id")
    private Long id;

    @ApiModelProperty("名字")
    private String name;
}

测试

访问:http://localhost:8080/product/query?id=1352213368413982722

结果

出现问题

从上边可以看到,并没有问题。

为什么没有出问题?

  1. 前端传入后端:SpingMVC会自动将String类型的ID转为Long类型,不会出问题
  2. 后端响应给前端:是JSON格式,与JS没有关系,不会出问题

什么时候会出问题?

前端接收到JSON之后,将其序列化为JS对象,然后进行其他操作。在JSON转JS对象时就会出问题,如下:

可以看到,原来id为1352213368413982722,序列化为JS对象后变成了 1352213368413982700

代码为:

const json = '{"id": 1352213368413982722, "name": "鼠标"}';
const obj = JSON.parse(json);

console.log(obj.id);
console.log(obj.name);

原因分析

Java后端Long类型的范围

  1. -2^63~2^63,即:-9223372036854775808~9223372036854775807,它是19位的。
  2. 这个数字可以通过方法获得:Long.MAX_VALUE、Long_MIN_VALUE。

前端JS的数字类型的范围

  1. -2^53~2^53,即:-9007199254740991~9007199254740991,它是16位的。
  2. 这个数字可以通过方法获得:Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER。

结论

可见,Java后端的Long宽度大于前端的。雪花算法一般会生成18位或者19位宽度的数字,那么这时就会出问题。

解决方案

此内容仅限VIP查看,请先
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录