場景重現:
最近在開發 狐小E智慧辦公 項目時,寫ajax時遇到一個小坑,之前都是做后端開發,對前端js代碼沒有深入了解,只是會使用相關函數,當開發某個功能時,列表已經開發完成,點擊列表跳轉詳情時老是報找不到數據錯誤,調試后發現每次后端返回的列表里有id,而查詳情時,也是帶着id,但是在數據庫卻無法查到。最終仔細對比發現后端返回列表的id和ajax里接收的id不一致。id返回到前端后已經不是正確的值了。發現只要后端返回的是long 類型的值 就會一定機率出現前端的值與后端接收的不一致的情況。
JS內置有32位整數,而number類型的安全整數是53位。如果超過53位,則精度會丟失。也就是后端直接返回的Long類型數據超過53位,則前端接收時就會丟失精度。
① 修改對應后端的類,返回的VO對象Long類型字段轉換為String類型,或者新定義一個String類型的字段將原始的Long類型值 toString()后存入即可。這樣改的缺點就是需要改動的代碼較多,不推薦。
例如: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類型長度是否會影響業務。
在參與開發 狐小E智慧辦公項目中,就是這樣一點點的經驗慢慢的積累起來,希望每天能看到自己的進步。