飞蛾扑火时一定是极快乐幸福的。——三毛
我们在进行开发时可能会遇到这样一个坑,那就是js代码的精度丢失

可以看到16位以后就会出现精度丢失的问题
我们定义一个简单接口,这里用com.baomidou.mybatisplus.core.toolkit.IdWorker.getId()生成19位为Long类型的id
| @GetMapping("json")@ResponseBody
 public Ruben json() {
 return new Ruben(IdWorker.getId());
 }
 
 | 
返回的Ruben对象
| 
 
 
 public class Ruben {
 
 private Long id;
 
 public Ruben(Long id) {
 this.id = id;
 }
 
 public Long getId() {
 return id;
 }
 
 public void setId(Long id) {
 this.id = id;
 }
 }
 
 | 
请求一下
可以看到我们Response中是正常的

但Preview中就出现了精度丢失的问题

当然,我们可以转换为string,这样就不会出现精度丢失问题
但是,我们在返回json格式数据的接口中如果要一个一个处理的话非常麻烦,我们可以配置一下WebMvcConfigurer
如果我们使用的Mvc默认的jackson,只需如下配置即可
| package com.ruben.simplethymeleaf.config;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import java.util.List;
 
 
 
 
 
 
 
 @Configuration
 @EnableWebMvc
 public class SpringMvcConfig implements WebMvcConfigurer {
 
 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
 
 final ObjectMapper objectMapper = new ObjectMapper();
 SimpleModule simpleModule = new SimpleModule();
 simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
 objectMapper.registerModule(simpleModule);
 MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
 converter.setObjectMapper(objectMapper);
 converters.add(converter);
 }
 
 }
 
 | 
然后我们配置完后重启项目
再次请求,可以看到默认将Long给我们转成了String

假设你用的是FastJson,则需要如下配置
| package com.ruben.simplethymeleaf.config;
 import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.alibaba.fastjson.support.config.FastJsonConfig;
 import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.MediaType;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import java.util.ArrayList;
 import java.util.List;
 
 
 
 
 
 
 
 @Configuration
 @EnableWebMvc
 public class SpringMvcConfig implements WebMvcConfigurer {
 
 
 
 
 
 
 
 
 
 
 
 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
 FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
 
 List<MediaType> supportedMediaTypes = new ArrayList<>();
 supportedMediaTypes.add(MediaType.APPLICATION_JSON);
 supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
 supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
 supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
 supportedMediaTypes.add(MediaType.APPLICATION_PDF);
 supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
 supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
 supportedMediaTypes.add(MediaType.APPLICATION_XML);
 supportedMediaTypes.add(MediaType.IMAGE_GIF);
 supportedMediaTypes.add(MediaType.IMAGE_JPEG);
 supportedMediaTypes.add(MediaType.IMAGE_PNG);
 supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
 supportedMediaTypes.add(MediaType.TEXT_HTML);
 supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
 supportedMediaTypes.add(MediaType.TEXT_PLAIN);
 supportedMediaTypes.add(MediaType.TEXT_XML);
 fastJsonConverter.setSupportedMediaTypes(supportedMediaTypes);
 FastJsonConfig fjc = new FastJsonConfig();
 
 
 
 fjc.setSerializerFeatures(SerializerFeature.BrowserCompatible);
 fastJsonConverter.setFastJsonConfig(fjc);
 converters.add(fastJsonConverter);
 }
 }
 
 | 
同样的效果如下

当然,有种情况,是我们没有用ajax请求Json数据,而是直接使用thymeleaf进行渲染
在页面上当然没问题,但在js代码里就会出现精度丢失
我们写一个接口跳转到对应页面
| @GetMappingpublic String index() {
 request.setAttribute("id", IdWorker.getId());
 request.setAttribute("ruben", new Ruben(IdWorker.getId()));
 return "index";
 }
 
 | 
然后在页面上渲染我们的id和ruben.id
| <!DOCTYPE html><html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>ruben</title>
 </head>
 <body>
 <div>
 <div th:text="${id}"></div>
 <div>[[${ruben.id}]]</div>
 </div>
 </body>
 </html>
 
 | 
可以看到页面是成功渲染

但如果我们在js里替换
| <!DOCTYPE html><html lang="en">
 <head>
 <meta charset="UTF-8">
 <title>ruben</title>
 </head>
 <body>
 <div>
 <div th:text="${id}"></div>
 <div>[[${ruben.id}]]</div>
 </div>
 <script th:inline="javascript">
 var id = [[${id}]]
 console.log(id)
 </script>
 <script th:inline="javascript">
 /*<![CDATA[*/
 var id = /*[[${id}]]*/ 'Achao';
 /*]]>*/
 console.log(id)
 </script>
 </body>
 </html>
 
 | 
可以看到浏览器控制台里确实是替换成功了

但我们控制台输出的数据出现精度丢失了

所以我们可以如下解决,直接在外层套个引号即可
| <script th:inline="javascript">var id = '[[${id}]]'
 console.log(id)
 </script>
 
 | 
效果如下

打印出来可以看到第一个也正确
