目录
- 起因
- 真相
- 解决方案
起因
众所周知,浏览器在处理 Long类型(比如雪花算法生成的id)时,往往会出大事情。
浏览器在处理长整型(Long)类型时可能会遇到问题,主要原因是浏览器在处理数字时有限制。一般来说,浏览器的JavaScript引擎使用64位浮点数来表示数字。然而,JavaScript的Number类型只能安全地表示-253到253之间的整数。当超过这个范围时,会有精度丢失的问题。
例如,如果使用雪花算法生成的长整型id超过了JavaScript Number类型的范围,就会出现问题。雪花算法生成的id是一个非常大的数字,如果直接在浏览器中处理,可能会导致精度丢失或溢出。
此外,浏览器在处理长整型时还可能遇到性能问题。处理大数字可能会导致浏览器的运算速度变慢,因为浏览器需要更多的计算资源。
为了避免这些问题,一种常见的做法是将长整型转换为字符串进行处理,而不是直接使用数字类型。这样可以避免精度丢失和性能问题。
在 Spring for Java中,我们可以这样处理:
@JsonComponent
public class JsonConfig {/*** 添加 Long 转 json 精度丢失的配置*/@Beanpublic ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();SimpleModule module = new SimpleModule();module.addSerializer(Long.class, ToStringSerializer.instance);module.addSerializer(Long.TYPE, ToStringSerializer.instance);objectMapper.registerModule(module);return objectMapper;}
}
但是最近在捣鼓 SpringBoot for kotlin,orm框架用的是 ktorm。此时这个配置突然就失效了
// kotlin版本的
@Configuration
class KtormConfiguration {@Autowiredlateinit var dataSource: DataSource@Beanfun database(): Database {return Database.connectWithSpringSupport(dataSource)}fun ktormModule(): Module {return KtormModule()}@Beanfun jacksonObjectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {val objectMapper = builder.createXmlMapper(false).build<ObjectMapper>()val module = SimpleModule()module.addSerializer(Long::class.java, ToStringSerializer.instance)module.addSerializer(java.lang.Long.TYPE, ToStringSerializer.instance)objectMapper.registerModule(module)objectMapper.registerModule(ktormModule())return objectMapper}
}
而debug看到的返回值却是:
一半是string,一半还是number??
然后我很合理地开始怀疑是不是我这一手 BaseJavaEntity 玩瞎了,我开始变换方式(kotlin有三种方式拓展data class,见:Kotlin 数据类继承:扩展数据类。最后都失败了…
真相
最后发现是:转成功的是Long
,没转成功的是Long?
…
Long?
表示这值可以为Long也可以为null
那我难道要改成 module.addSerializer(Long?::class.java, ToStringSerializer.instance)
?结果报错了
解决方案
直到我查到了这篇博客:https://cloud.tencent.com/developer/article/2345831
只需要调用 Long::class.javaObjectType
,Long::class.javaPrimitiveType
即可。
@Bean
fun jacksonObjectMapper(builder: Jackson2ObjectMapperBuilder): ObjectMapper {val objectMapper = builder.createXmlMapper(false).build<ObjectMapper>()val module = SimpleModule()module.addSerializer(Long::class.javaObjectType, ToStringSerializer.instance)module.addSerializer(Long::class.javaPrimitiveType, ToStringSerializer.instance)objectMapper.registerModule(module)objectMapper.registerModule(ktormModule())return objectMapper
}
搞定(kotlin真的是一门神奇的语言