前端接收Long类型数据精度丢失问题

项目场景:

后端数据库中主键使用Bigint类型,新增时通过MyBatis-Plus设置ID策略为雪花ID,后端接口返回主键为Long类型。


问题描述

后端接口编写完成后,在postman中测试新增、修改、删除和详情接口都正常。在同前端调试过程中发现无法通过主键对后端数据进行操作。


原因分析:

首先听到前端反馈这个问题时,内心深处在想这个前端怎么回事,怎么接口都不会调用(PS:我写的接口怎么可能有BUG),保险起见还是暗戳戳的通过postman测试了一遍接口发现一切正常,又打开测试环境通过浏览器检查查看接口调用情况,发现前端传递到后端的主键同后端返回的主键不相同。(PS:看果然是你前端的问题吧)


解决方案:

查询资料后发现前端的数据格式没有Long类型只有Number 和 BigInt,在接收后端数据时默认为Number 类型,当超出其安全范围(即大于 2^53 - 1)的整数,会丢失精度。
解决方案一:后端通过拦截器的方式在接口返回时将全部的Long类型转换为String类型返回到前端
解决方案二:前端在接收时强制转换为BigInt
解决方案三:前端使用支持大整数的库
本人更加倾向于采用第一种解决方案来解决这个问题,毕竟这个处理更加简单方便,代码如下:

/**
 * 序列化为json时,将所有的long变成string,js中数字类型长度小于java中long值长度
 * EnableWebMvc 开启springmvc的一个注解
 */
@EnableWebMvc
@Configuration
public class JacksonConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
        // 反序列化时忽略多余字段
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 注册
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
    }
}
<think>好的,我现在需要解决用户的问题前端如何正确接收Hessian2序列化后的long类型数据长度。首先,我得回忆一下Hessian2序列化的相关知识。Hessian2是一种二进制协议,用于跨语言的数据传输,比如在Java后端和前端之间。用户提到的问题可能是在反序列化时,前端接收到的long类型数据长度不正确,导致数据解析错误。 首先,Hessian2对long类型的处理方式是什么?根据之前的引用,Hessian2使用特定的编码格式来处理不同类型数据。对于long类型,可能涉及到变长编码或者固定长度的处理。比如,Hessian2可能会根据数值的大小选择不同的编码方式,比如使用1到8字节来表示不同的整数范围。如果前端在解析时没有正确识别这些编码规则,就会导致长度解析错误,进而数据错误。 用户提供的引用中提到了序列化失败的情况,特别是使用ImmutableList时的问题,但用户现在的问题是关于long类型的长度。可能需要参考Hessian2的官方文档或规范,了解long类型的具体编码方式。例如,Hessian2中的long类型可能以特定的字节开头,比如'L'(0x4c)后跟8字节的大端表示。或者,对于较小的数值,可能使用更紧凑的编码方式,比如直接用一个字节加上数值。如果前端没有正确处理这些不同的情况,就会出错。 接下来,考虑前端如何正确解析。前端可能需要使用支持Hessian2反序列化的库。例如,在JavaScript中,可能需要使用hessian.js这样的库。如果前端没有正确配置或使用这样的库,可能会导致解析错误。需要检查前端是否正确地引入了相应的库,并且版本是否支持Hessian2的long类型解析。 另外,用户提到的引用[3]中提到了序列化扩展包的问题,如果后端使用了特定的Hessian2实现,比如Dubbo的扩展包,前端可能需要对应的处理方式。例如,Dubbo的Hessian2可能有自定义的序列化方式,需要前端适配这些扩展。 可能的解决方案包括: 1. 确保前端使用的Hessian2解析库支持long类型的正确解码,特别是处理不同长度的编码。 2. 检查前后端的序列化和反序列化配置是否一致,比如是否都使用了正确的Hessian2版本。 3. 在传输数据时,确认数据在网络传输过程中没有被截断或修改,比如使用正确的Content-Length头或分块传输。 4. 调试时,可以对比后端序列化后的二进制数据前端接收到的数据,确认是否一致。如果不一致,可能是网络传输问题;如果一致,则是解析库的问题。 另外,可能需要查看具体的错误现象,比如前端接收到的数据长度是固定的还是变长的,是否有溢出或截断的情况。例如,JavaScript的Number类型是双精度浮点数,可能导致大整数精度丢失。这时可能需要将long类型作为字符串传输,或者在解析时使用BigInt类型来处理。 总结一下,解决步骤可能包括: - 确认前后端使用的Hessian2库兼容,特别是对long类型的处理。 - 检查前端反序列化代码是否正确处理了Hessian2的编码规则。 - 验证网络传输中数据的完整性。 - 必要时调整数据类型或使用兼容的序列化方式。 相关问题可能涉及Hessian2的其他数据类型处理、性能优化或不同语言间的兼容性问题。</think>### 前端正确接收Hessian2序列化long类型数据的解决方案 Hessian2序列化协议对`long`类型采用**变长编码**策略,根据数值范围选择1-8字节存储[^1]。前端需通过以下步骤确保正确解析: 1. **确认前端解析库支持Hessian2标准** - 使用标准库如`hessian.js`,验证版本是否支持`long`类型解码 - 示例代码: ```javascript const Hessian = require('hessian.js'); const decoder = new Hessian.Decoder(buffer); const value = decoder.readLong(); // 显式调用long类型解析方法 ``` 2. **处理JavaScript数值精度限制** - 对超过$2^{53}$的数值,使用字符串或`BigInt`类型接收 - 配置解码器特殊处理: ```javascript decoder.options({ bigint: true }); // 启用BigInt模式 ``` 3. **验证字节流完整性** - 检查HTTP头部`Content-Length`与实际接收字节数是否一致 - 使用Chrome开发者工具查看网络请求的原始二进制数据: ``` // 示例有效负载 4c 00 00 00 00 00 00 1a 38 // 表示long型数值6700 ``` 4. **跨语言类型映射** | Hessian2类型标记 | 字节长度 | 前端映射类型 | |------------------|----------|--------------| | 0x4c (L) | 8 | BigInt | | 0x38-0x3f (压缩) | 1 | Number | ### 调试方法 1. 构造测试用例验证边界值: ```python # 后端生成测试数据 [-2^63, -2^53, 0, 2^53-1, 2^63-1] ``` 2. 使用HEX对比工具验证前后端二进制一致性 3. 监控反序列化时的精度警告: ```javascript if (Number(value) !== value) { console.warn('精度丢失, 建议启用BigInt'); } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值