问题描述:
后端代码返回值为String,但是这个字符串为纯数字!!!纯数字,实际上是雪花算法生成的Long类型的标识,但是因为某些原因我进行了稍微的修改,使数据标志占高五位,造成生成的ID超过本来的长度,继而造成了后续的一系列问题(在保证接口返回值类型不变的情况下保证新旧版本都能获取到返回值而不是精度缺失后两位变成0)
问题解决:
-
强行变成字符(返回值为String类型,即ID)
这个方法是我在查找问题的时候使用的。
我能够确保后端接口返回值没有问题,返回值也是String类型,但是到前端会自动变成number类型数据(console.log(typeof(res.data))
测出来的),心里一万头草泥马奔过,为了最快速的解决,我决定强行转String!!@RequestMapping(value = "csdn", consumes = "application/json;charset=UTF-8") public String csdn(@RequestBody String c) { log.info("调用Service接口,返回String类型数据"); // 假设是service调用返回值 String id = "1441163676357369856"; // return id;// 此时返回前端res.data展示为1441163676357369900,被当做number处理,造成精度缺失 return "\"" + id + "\"";// 强行转成String,硬加 " 字符,前端当做字符串,无问题 }
然而这个方法太不友善,好多接口都要改(怪就怪自己数据库属性设置是varchar而不是long)。
-
设置序列化规则
此种情况返回值为Long类型数据(数据库以及实体类慎重选择)@RequestMapping(value = "csdn", consumes = "application/json;charset=UTF-8") public Long csdn(@RequestBody String c) { log.info("调用Service接口,返回String类型数据"); // 假设是service调用返回值 String id = "1441163676357369856"; return Long.parseLong(id);// 返回Long类型数据 }
在不改动已完成service接口情况下,为了防止之后再次发生此种情况,后续数据库表字段设置为long类型,直接返回Long类型数据,不需要再转一次。
下面配置,设置所有的Long类型转成String传给前端package org.pet.king.config; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { /** * 解决返回值乱码问题 */ @Bean public HttpMessageConverter<String> responseBodyStringConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); return converter; } /** * 修改StringHttpMessageConverter默认配置 * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(responseBodyStringConverter()); MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); SimpleModule simpleModule = new SimpleModule(); /** * 将Long,BigInteger序列化的时候,转化为String,某些类里面的Long类型数据超长造成精度缺失可以在属性上使用@JsonSerialize注解 */ simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); objectMapper.registerModule(simpleModule); messageConverter.setObjectMapper(objectMapper); converters.add(messageConverter); } }
至此,数据传到前端debugger的时候会带
""
,不会再出现精度缺失情况,个人建议数据传输尽量选择String,Long类型的数据可以通过getString拿到,但是String不能通过getLong获取。