1. 程式人生 > 實用技巧 >關於Ajax接收 後臺返回的 Long型別資料的處理思路

關於Ajax接收 後臺返回的 Long型別資料的處理思路

場景重現:

最近在開發狐小E智慧辦公專案時,寫ajax時遇到一個小坑,之前都是做後端開發,對前端js程式碼沒有深入瞭解,只是會使用相關函式,當開發某個功能時,列表已經開發完成,點選列表跳轉詳情時老是報找不到資料錯誤,除錯後發現每次後端返回的列表裡有id,而查詳情時,也是帶著id,但是在資料庫卻無法查到。最終仔細對比發現後端返回列表的id和ajax裡接收的id不一致。id返回到前端後已經不是正確的值了。發現只要後端返回的是long 型別的值 就會一定機率出現前端的值與後端接收的不一致的情況。

問題產生原因:

JS內建有32位整數,而number型別的安全整數是53位。如果超過53位,則精度會丟失。也就是後端直接返回的Long型別資料超過53位,則前端接收時就會丟失精度。

解決方案:

① 修改對應後端的類,返回的VO物件Long型別欄位轉換為String型別,或者新定義一個String型別的欄位將原始的Long型別值 toString()後存入即可。這樣改的缺點就是需要改動的程式碼較多,不推薦。
② 通過全域性控制新增轉換器 通過fastJson的轉換 或者jackson 來實現全域性將long型別轉為String.

例如:SpringBoot預設使用jackson ,則只需要增加轉換器即可 程式碼如下`


@EnableWebMvc
@Configuration
public class WebJsonConverterConfig extends WebMvcConfigurerAdapter {
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        
        objectMapper.registerModule(simpleModule);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
    }
}

這樣通過全域性控制使程式碼修改量最小,並且對所有Long型別欄位都可以起到轉換。

③ 若Long型別資料的生成不是通過資料庫生成,而是在程式碼邏輯中呼叫工具類或者id生成器服務生成Long型別資料,那可以在根源上調整Long型別資料生成策略,使其保持在53位之內,那直接返回Long型別資料也不會丟失精度。

我們開發狐小E智慧辦公時,正好所有的Long型別資料都是呼叫一個統一的生成Long型別資料的服務,這樣我們評估了業務需要的Long型別資料在53位之內也不會重複,所以改動了這個服務,使產生的Long型別資料的範圍都在53位之內,這樣前端就不會出現丟失精度問題了。但是需要根據業務判斷 限制Long型別長度是否會影響業務。

最終解決ajax丟失精度的問題返回String 或者 在精度範圍內返回long 只要結果是正確的即可。

在參與開發狐小E智慧辦公專案中,就是這樣一點點的經驗慢慢的積累起來,希望每天能看到自己的進步。