引入雪花算法当作生成主键,遇到问题如下:
前端请求获取的response的值,ID和后端返回的值不一致,排查了很久发现是前端在获取时将Long类型值转换超范围导致丢失精度
Java后端Long类型的范围
- -263~263,即:-9223372036854775808~9223372036854775807,它是19位的。
- 这个数字可以通过方法获得:Long.MAX_VALUE、Long_MIN_VALUE。
前端JS的数字类型的范围
- -253~253,即:-9007199254740991~9007199254740991,它是16位的。
- 这个数字可以通过方法获得:Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER。
解决办法
- 全局处理自定义ObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 全局配置序列化返回 JSON 处理
SimpleModule simpleModule = new SimpleModule();
// 将使用String来序列化Long类型
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
- 局部处理:
在字段上加:@JsonSerialize(using= ToStringSerializer.class)
@Id
@GeneratedValue(generator = "myIDGenerator")
@JsonSerialize(using= ToStringSerializer.class)
private Long id;
注意
:全局处理会将分页参数页码、总条数值也转成string类型
- 在application.yml中加上以下配置,这个办法会将所有数字都变成字符串,包括long和int类型
spring:
jackson:
generator:
writeNumbersAsStrings: true
- 如果想要前端不丢失精度,JSON中的id就不能是long类型,改为String类型就好了。
这个方案如果此id用的类少,就可以改id的数据类型,但是当用到的类多的话要改过来就需要花很长时间,并且不能保证都能改过来,而且不会出问题。