springboot解决Long类型值传递给页面时精度丢失的问题!
Posted 努力lshdnks
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot解决Long类型值传递给页面时精度丢失的问题!相关的知识,希望对你有一定的参考价值。
最近项目中遇到个问题,主键id用的Long类型,Long类型超过16位时传递给前端丢失精度。
网上搜了下,解决办法有很多,大体分为两种,写个全局转换器和在bean主键id上添加注解,其实解决的本质是将Long类型在序列化json时转为String字符串类型,这样就不存在丢失精度了。
1.全局转换器
springboot2以下的版本写个配置类实现WebMvcConfigurerAdapter重写configureMessageConverters方法。
springboot2及其以上的版本写个配置类实现WebMvcConfigurer重写configureMessageConverters方法(2以上版本WebMvcConfigurerAdapter已经废弃了,不推荐使用)。
代码如下:
package com.thecityos.city.indicator.admin.common.config; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.alibaba.fastjson.serializer.SerializeConfig; import com.alibaba.fastjson.serializer.ToStringSerializer; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; /** * @title: WebMvcConfig * @description: 自定义转换 * @author: * @date 2019-08-03 16:23 */ @Configuration public class WebMvcConfig implements WebMvcConfigurer /** * 解决主键Long类型返回给页面时,页面精度丢失的问题,时间格式化返回 * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); //格式化json数据格式 FastJsonConfig fastJsonConfig = new FastJsonConfig(); //序列化时避免精度丢失,转换为字符串 SerializeConfig serializeConfig = SerializeConfig.globalInstance; serializeConfig.put(BigInteger.class, ToStringSerializer.instance); serializeConfig.put(Long.class, ToStringSerializer.instance); serializeConfig.put(Long.TYPE, ToStringSerializer.instance); fastJsonConfig.setSerializeConfig(serializeConfig); fastJsonConfig.setDateFormat("yyyy-HH-dd HH:mm:ss"); fastConverter.setFastJsonConfig(fastJsonConfig); List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastMediaTypes.add(MediaType.APPLICATION_JSON); fastConverter.setSupportedMediaTypes(fastMediaTypes); converters.add(0,fastConverter);
当然你要是hold住全场可以自己继承WebMvcConfigurationSupport重写configureMessageConverters,特别注意的是,继承该类后springboot的默认自动配置会失效,需要你自己根据需要配置一些东西。
PS:一些常见的问题,写了后没生效,大概率是虽然添加了转换器进去,但是没在首位或者被后续一些配置挤在了后面,因为springmvc处理时,converters里包含很多转换器,但是它匹配到第一个转换器后就直接使用了,后续转换器无效。
我就遇到了项目里因为引用了
<dependency> <groupId>com.github.rkonovalov</groupId> <artifactId>json-ignore</artifactId> <version>1.0.14</version> </dependency>
这个是解决controller层想屏蔽或者只返回某些字段的一个注解依赖。
但它有个类FilterRegister实现了WebMvcConfigurer并且重写了extendMessageConverters
如下:
package com.jfilter.components; import com.jfilter.EnableJsonFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.*; import java.util.List; /** * This class used for register FilterConverter in Spring converter list * * <p>Class depends from @link EnableJsonFilter annotation */ @Configuration public class FilterRegister implements WebMvcConfigurer private FilterConfiguration filterConfiguration; @Autowired public FilterRegister(FilterConfiguration filterConfiguration) this.filterConfiguration = filterConfiguration; @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) // Do nothing @Override public void configurePathMatch(PathMatchConfigurer configurer) // Do nothing @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) // Do nothing @Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) // Do nothing @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) // Do nothing @Override public void addFormatters(FormatterRegistry registry) // Do nothing @Override public void addInterceptors(InterceptorRegistry registry) // Do nothing @Override public void addResourceHandlers(ResourceHandlerRegistry registry) // Do nothing @Override public void addCorsMappings(CorsRegistry registry) // Do nothing @Override public void addViewControllers(ViewControllerRegistry registry) // Do nothing @Override public void configureViewResolvers(ViewResolverRegistry registry) // Do nothing @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) // Do nothing @Override public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) // Do nothing /** * Add converter if filtration is enabled * * @param converters list of @link HttpMessageConverter */ @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) if (filterConfiguration.isEnabled()) converters.add(0, new FilterConverter(filterConfiguration)); @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) // Do nothing @Override public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) // Do nothing @Override public Validator getValidator() return null; @Override public MessageCodesResolver getMessageCodesResolver() return null;
这就导致了,我自定义的那个配置类解决Long类型丢失的转换器被挤在了后面,所以没有生效,真是醉了,后面研究了一天还是没有啥好的解决办法,除非不用上面那个依赖吧,后续空了再研究。
目前的解决办法时,在实体bean的Long类型字段上加
/** * 主键 */ @JsonSerialize(using = ToStringSerializer.class) private Long id;
/** * 创建时间 */ @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") private Date createTime;
以上是关于springboot解决Long类型值传递给页面时精度丢失的问题!的主要内容,如果未能解决你的问题,请参考以下文章
浏览器响应数据long型超长自动转换精度丢失-JavaScript 整数精度丢失问题-springboot解决Long类型数据传入前端损失精度
解析graphqls类型文件时字段输入类型Long不存在,怎么解决?
Jsp 视图页面在 Spring Boot 中不呈现。如何解决?