• 后端Long类型传到前端精度丢失的正确解决方式


    原因:前端js对Long类型支持的精度不够,导致后端使用的Long传到前端丢失精度,比如现在分布式id生成算法“雪花算法”在使用中就会出现问题。

    解决方式:

    1、后端的Long类型的id转用String存储,不推荐,失去了其Long类型本身的意义。

    2、在Long类型字段上使用注解标明序列化方式,代码量不大的情况可以考虑

        @JsonSerialize(using = ToStringSerializer.class)
        private Long id;

    3、实现WebMvcConfigurer接口,重写configureMessageConverters方法

      @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            MappingJackson2HttpMessageConverter jackson2HttpMessageConverter =
                    new MappingJackson2HttpMessageConverter();
    
            ObjectMapper objectMapper = new ObjectMapper();
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
            objectMapper.registerModule(simpleModule);
            jackson2HttpMessageConverter.setObjectMapper(objectMapper);
            converters.add(jackson2HttpMessageConverter);
            converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        }

    但是这种方式需要开启@EnableWebMvc注解。

    开启这个注解意味着springboot的mvc等自动配置失效,所以这个方式实际上也是不可取的。

    类似的还有继承WebMvcConfigurationSupport类,也会导致一些配置失效https://www.cnblogs.com/asker009/p/12752716.html

    类似不可取的还有重写HttpMessageConverters,这会覆盖其他的类型转换。

     
    @Configuration
    public class LongToJsonConfig {
        public LongToJsonConfig() {
        }
     
        @Bean
        public HttpMessageConverters customConverters() {
            MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
            ObjectMapper objectMapper = new ObjectMapper();
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
            objectMapper.registerModule(simpleModule);
            jackson2HttpMessageConverter.setObjectMapper(objectMapper);
            return new HttpMessageConverters(new HttpMessageConverter[]{jackson2HttpMessageConverter});
        }
    }

    以上方式基本都不可取。

    4、重新注册ObjectMapper的Long类型序列化方式,推荐使用,暂时没发现问题。

    @Configuration
    public class LongClassMessageConverter implements InitializingBean {
    
        @Resource
        ObjectMapper objectMapper;
    
        private SimpleModule getSimpleModule() {
    
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            // 暂时放弃对小long的转换,约定与前端交互数据时,大Long全部转换成字符串
    //        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
            objectMapper.registerModule(simpleModule);
            return simpleModule;
        }
    
    
        @Override
        public void afterPropertiesSet() {
            SimpleModule simpleModule = getSimpleModule();
            objectMapper.registerModule(simpleModule);
        }
    }

    5、重新构建Jackson序列化方式,与第四点类似的解决方式,推荐使用。

    @Configuration
    public class JacksonConfig {
        /**
         * Jackson全局转化long类型为String,解决jackson序列化时传入前端Long类型缺失精度问题
         */
        @Bean
        public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
            Jackson2ObjectMapperBuilderCustomizer cunstomizer = new Jackson2ObjectMapperBuilderCustomizer() {
                @Override
                public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
                    jacksonObjectMapperBuilder.serializerByType(BigInteger.class, ToStringSerializer.instance);
                    jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance);
    //                jacksonObjectMapperBuilder.serializerByType(Long.TYPE, ToStringSerializer.instance);
                }
            };
            return cunstomizer;
        }
    }

    6、以上方式针对springboot默认的Jackson序列化,fastjson等其他json组件类似处理。

    7、如果前端自身涉及到Long类型的计算,那么需要前端自己实现Long类型支持,参考:https://github.com/dcodeIO/long.js

  • 相关阅读:
    VC 使用json cpp 静态库 问题解决
    <转>c++ builder JSONCPP 注意事项 XE2 解决编译问题 _Mfl
    窥探try ... catch与__try ... __except的区别
    二叉树与其它树
    《DirectX 9.0 3D游戏开发编程基础》 第二章 绘制流水线 读书笔记
    《DirectX 9.0 3D游戏开发编程基础》 第一章 初始化Direct3D 读书笔记
    《DirectX 9.0 3D游戏开发编程基础》必备的数学知识 读书笔记
    windows lua 多线程 线程同步
    <转>多线程中的lua同步问题
    php 检查email电子邮件函数(奇葩写法)
  • 原文地址:https://www.cnblogs.com/asker009/p/12888388.html
Copyright © 2020-2023  润新知