Long型的惊天巨坑

2020-04-29  本文已影响0人  hekirakuno

后端使用雪花发号器生成的long型作为业务主键,在数据库与后端中,均表现正常,然后返回前端时,出现了精度不准确的问题。


数据库数据 后端获取数据正常 返回前端后数据精度丢失

以前总是不理解,为什么后端提供了这么多数据类型,但是前辈们设计系统的时候都喜欢全员字符串的设计。自己设计开发写的越来越多之后慢慢还是了解了string的安全之处。文本就是最纯粹也最final的东西。
比如这个long型,在前端无法精确表现。这是js中num精度的问题。

那么要怎么解决这种问题呢?
首先,考虑沿袭前辈们的做法,替换成string返回前端。
或者,要求前端支持long型。
第二种做法对我来说太不安全了。
所以,我还是考虑替换成string返回前端吧。泪流满面。

先看下转换结果:


long型用string返回

作为文本,它已经不存在精度问题了。
那么是怎么做的呢?
直接上代码:

/**
 * *****************************************************
 * Copyright (C) 2020 bytedance.com. All Rights Reserved
 * This file is part of bytedance EA project.
 * Unauthorized copy of this file, via any medium is strictly prohibited.
 * Proprietary and Confidential.
 * ****************************************************
 **/
package com.hekiraku.gemini.aop.converters;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.math.BigInteger;
import java.util.List;

/**
 * 全局类型转换器
 * 需要configuration的注解,把它当作一个配置类;
 * 需要继承 WebMvcConfigurationSupport ,把配置装配进去
 */
@Configuration
public class MyConverters extends WebMvcConfigurationSupport {
    //重写jackson的转换器方法,添加自定义的规则
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        //如果属性为空""或者null都不序列化,返回的json中没有这个字段,对移动端更省流量
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        SimpleModule simpleModule = new SimpleModule();
        //配置Long型转化为String的规则
        simpleModule.addSerializer(Long.class, new ToStringSerializer());
        simpleModule.addSerializer(Long.TYPE, new ToStringSerializer());
        //配置BigInteger型转化为String的规则
        simpleModule.addSerializer(BigInteger.class, new ToStringSerializer());
        objectMapper.registerModule(simpleModule);
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }
}

上一篇 下一篇

猜你喜欢

热点阅读