雪花ID算法 - Long 类型 id 返回前端精度丢失 (通过序列化解决)

原因:

js 的 number 类型支持的最大值是9007199254740992 (2 的 53次方 -1),溢出之后的精度会丢失,导致前后端的值不一致。
java 的 long 类型最大值为 9223372036854775807,远高于 js number类型的最大值,所以这个坑就出现了。

解决方案:

方案一

  1. id-type: ID_WORKER_STR
    简单来说就是 id 转 为string类型,db和生成的id数据类型都改为 string 类型
    缺点:牺牲了 long 类型的性能优势

方案二

可以在每个实体类的id字段上加注解

	@JsonFormat(shape = JsonFormat.Shape.STRING)
	private Long id;

方案三

  1. 通过 json 序列化做全局处理,传给前端的是字符串,到后台依然是 long 类型
    
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.alibaba.fastjson.serializer.ValueFilter;
    import com.alibaba.fastjson.support.config.FastJsonConfig;
    import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author :XiaoHui Yang
     * @version : 1.0.0
     * @description: 自定义JsonHttpMessageConverter解决long类型id丢精度问题
     * @date :Created in 2020/6/28 14:41
     * @modified By:
     */
    @Configuration
    public class CustomFastJsonHttpMessageConverter {
    
        @Bean
        public HttpMessageConverters fastJsonHttpMessageConverters() {
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
    
            List<SerializerFeature> list = new ArrayList<>();
            list.add(SerializerFeature.PrettyFormat);
            list.add(SerializerFeature.WriteMapNullValue);
            list.add(SerializerFeature.WriteNullStringAsEmpty);
            list.add(SerializerFeature.WriteNullListAsEmpty);
            list.add(SerializerFeature.QuoteFieldNames);
            list.add(SerializerFeature.WriteDateUseDateFormat);
            list.add(SerializerFeature.DisableCircularReferenceDetect);
            list.add(SerializerFeature.WriteBigDecimalAsPlain);
    
            fastJsonConfig.setSerializerFeatures(list.toArray(new SerializerFeature[list.size()]));
    
            fastConverter.setFastJsonConfig(fastJsonConfig);
            HttpMessageConverter<?> converter = fastConverter;
            fastJsonConfig.setSerializeFilters(new ValueFilter() {
                @Override
                public Object process(Object object, String name, Object value) {
                    if ((StringUtils.endsWith(name, "Id") || StringUtils.equals(name,"id")) && value != null
                            && value.getClass() == Long.class) {
                        return String.valueOf(value);
                    }
                    return value;
                }
            });
            return new HttpMessageConverters(converter);
        }
    }
    
    
    @Configuration
    public class WebConfig extends WebMvcConfigurationSupport {
        /*处理返回的long类型前端无法显示问题*/
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
            ObjectMapper objectMapper = new ObjectMapper();
            /**
             * 日期全局格式化
             * */
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));//GMT+8
            /**
             * 序列换成json时,将所有的long变成string
             * 因为js中得数字类型不能包含所有的java long值
             */
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
            objectMapper.registerModule(simpleModule);
            jackson2HttpMessageConverter.setObjectMapper(objectMapper);
            converters.add(jackson2HttpMessageConverter);
    
        }
    
        /*处理swagger doc.html无法显示问题*/
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    }
    
    

猜你喜欢

转载自blog.csdn.net/WXF_Sir/article/details/109778231#comments_27906823
今日推荐