今天写程序的时候,不小心又碰到了一个问题,困扰了好久,最后还是大佬出面才解决的这个问题
场景:中午的时候,前端突然告诉我,数据有些问题,大体就是好多数据都是重复的,导致前端的某些功能使用异常。然后我开始找问题,最先是觉得数据库中的数据出现大量重复了,然后我查了下数据库,发现并不是,甚至一条重复的都没有;之后我又去响应统一处理方法中看了一下,因为响应发送回前端需要经过这个地方,然后发现这里也没做处理。这个时候我有点慌了,感觉是代码出现BUG了,于是我对输出的响应结果全部做了打印,发现到响应数据发出去为止,数据都是正常的。这时候我就感觉是前端那边做了处理,才导致的这个问题,因为我后端发出的响应数据没有问题,这个时候前端发了一张NETWORK里面的请求截图给我看,数据还真出问题了,这个时候我真的是一脸懵逼,并不知道哪出问题了,纠结了好久。最后大佬出面看了一眼,就发现问题了。
大佬指出的问题所在:
Long可以存储的数字长度可以超过17位以上(出问题的那个字段存储的数字是17位以上的),但是JSON转码的时候是无法处理17位以上的超大数字的,这个时候JSON可能就会转码一条数字其它数字不做处理赋予相同的值,所以才导致的这个问题。
解决办法:
将17位以上的数字转成字符的形式;
- 1、数据库存储类型改成字符串(一般都不用,除非刚建表的时候)
- 2、在响应数据统一处理法中对17位以上的Long类型转型为字符类型再发送出去
2的具体实现方法:
package com.muyichen.demo.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
/**
* 序列化配置(只要有项目中有任何一个地方继承了WebMvcConfigurationSupport,那么该类无效)
* @author muyichen
* @version 1.0
*/
@Configuration
public class SerializerConfig implements InitializingBean {
/**
* 该对象是响应数据转化成json之前必须经过的一个类
*/
@Autowired
private ObjectMapper objectMapper;
/**
* 在对象序列化之前做处理
*/
@Override
public void afterPropertiesSet() {
if (objectMapper != null) {
//将Long类型转换成String类型
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
}
}
}
拓展一下:问什么调整ObjectMapper就能使得所有的相应输出对象的Long类型转为字符串类型?
原因很简单,以为@ResponseBody注解是通过这个类实现实体类对象到json字符串的改变,所以只要调整ObjectMapper,那么所有使用到@ResponseBody注解的响应对象中的Long类型字段就会被调整为String类型。
注意:
1、只要有项目中有任何一个地方继承了WebMvcConfigurationSupport,那么该方法无效;
2、return响应数据前先检查一下你所返回的数据类型是否是Long类型,笔者之前碰到个坑,就是因为使用了一个响应数据安全检查框架,这个框架把本应该是Long类型的数据向下转型成了Integer类型,导致笔者在测试的过程中,Long类型迟迟无法转换成字符串;