雪花算法踩坑 - 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 類型的性能優勢
  2. 通過 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);
    }
}

感謝閱讀,希望對你有幫助~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章