当前位置:   article > 正文

Spring Boot项目前后端Long类型数据传递失真问题的处理方式_springboot 返回long 失真

springboot 返回long 失真

场景介绍:

项目场景:目前市场上的大多数项目对于对象表建设的ID属性使用的是Long性并使用雪花算法生成,少量使用String的UUID,极少量的使用Long类型的自增长。

1 . Long型雪花算法ID
雪花算法 : 分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。

雪花算法
优点:雪花算法id是一个64bits的Long数据,第一位为零表示其为正数,最后12位为其序列号,生成的id既能完美契合分布式ID的需求,同时后12位序列号也能够保证主键的有序性。
缺点:雪花算法的长度是19(long型最多19位)位的,前端能够接收的数字最多只能是16位的,因此就会造成精度丢失,导致相关业务无法处理。

2 . UUID
UUID : 是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。在UUID的算法中,可能会用到诸如网卡MAC地址,IP,主机名,进程ID等信息以保证其独立性。
优点:UUID不是通过数据库的主键生成器生成的,在入库之前就能够获取到其主键,非常符合分布式主键的设计。
缺点:UUID没有规律可循,无法保证主键的插入顺序型。且UUID在意外情况下(mac地址等其他生成UUID的因素相同的情况)可能会出现UUID相同。

3 .自增Long型主键
优点:自增主键保证了,插入数据的主键永远比已有的数据的主键大。(看不懂就去复习数据结构)
缺点:需要等待插入完成才有主键,或者等待主键生成器返回才会有主键。不利于分布式的设计。


问题描述:

某次开发时前端直接给俺说ID传递到前端是失真了,俺一看果真如此,反应过来是ID过长导致失真,做个记录让遇到类似问题的小伙伴能够快速的解决。
错误如下:
分布式ID失效


原因分析:

雪花算法生成的分布式ID长度为19位,前端JS接收数字能够达到的最大精度为16位,因此导致前端得到的ID不是真正的ID,导致后续操作无法进行。
public class ThresholdConfigEntity implements Serializable {

    private static final long serialVersionUID = 1L;
	/** 雪花算法生成分布式ID */
    @TableId(value = "id",type = IdType.ID_WORKER)
    private Long id;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

解决方案:

解决的方式很简单,我们只需要将数据库中雪花算法生成的ID转换为String传递给前端就能够保证数据的可靠性!

  • 在相关需要转换的ID上加注解完成转换(需要在每一个res中的ID上加)
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@Data
public class BusinessTreeRes {

    /**
     * 方式一:JsonSerialize注解
     * 主键
     */
    @JsonSerialize(using = ToStringSerializer.class)
    private Long typeId;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 在拦截器中加Long型数据转换方法(推荐使用)
    第一种方法非常稳健,但比较繁琐,需要在和前端交互的每一个res中的ID上加入次注解,对于我这种十分懒惰的哥们儿是不实用滴,于是俺采用这一种在web层统一配置的懒人操作。
@Configuration
@EnableWebMvc
public class InterceptorConfig implements WebMvcConfigurer {
    /**
     * 方式二:拦截器转换
     * web层统一处理Long转String问题
     * @param converters 需要转换的对象
     */
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        //将Long转为string 解决id过大 js显示问题
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(0, jackson2HttpMessageConverter);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 自定义配置类
    如果你既没有在ID上加注释,也没有配置拦截器,也妹关系,直接写一个简单的配置类就完事儿了,因为这个转String的核心类就是:ObjectMapper 而已
/**
 * 类型转换配置
 *
 * @author xiefei15
 * @version 1.0
 * @date 2020/6/5 15:20
 */
@Configuration
public class DataTypeConvertConfig{
    /**
     *
     * 方式三:采用objectMapper注入
     */
    @Bean
    public ObjectMapper objectMapper (Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        SimpleModule simpleModule = new SimpleModule();
        // 直接将所有的Long类型转换为String
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

总结:

萝卜青菜,各有所爱,兄弟萌用自己喜欢的姿势完成Long类型转换即可。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/356992?site
推荐阅读
相关标签
  

闽ICP备14008679号