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不存在,怎么解决?

C++ 传递指针给函数

Jsp 视图页面在 Spring Boot 中不呈现。如何解决?

如何在 SqlData 实现中为 Long 类型的属性传递 NULL 值?

如何在MultipartEntity中传递long或int数据类型值?