Spring Mvc Long类型精度丢失
背景
在使用Spring Boot Mvc的项目中,使用Long类型作为id的类型,但是当前端使用Number类型接收Long类型数据时,由于前端精度问题,会导致Long类型数据转换为Number类型时的后两位变为0
Spring Boot Controller
以下代码提供一个Controller,返回一个Dto, Dto的id是Long类型的,其中id的返回数据是1234567890102349123
@CrossOrigin
注解表示可以跨域访问
@RestController()
@RequestMapping
public class LongDemoController {
@GetMapping("getLongValue")
@CrossOrigin(origins = "*")
public GetLongValueDto getLongValue(){
GetLongValueDto result = new GetLongValueDto();
result.setId(1234567890102349123L);
return result;
}
@Data
public static class GetLongValueDto{
private Long id;
}
}
前端调用
现在使用jquery调用后端地址,模拟前端调用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>spring boot mvc long</title>
</head>
<body>
<p>Long:<span id='resId'></span></p>
<p>Id类型:<span id='idType'></span></p>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
console.log('init');
$.ajax({url:"http://localhost:8080/getLongValue"})
.then(res=>{
console.log({
'getLongValue':res
});
$('#resId').text(res.id);
$('#idType').text(typeof res.id);
})
});
</script>
</body>
</html>
运行结果
通过输出结果和查看网络的内容,发现实际上id返回的结果是1234567890102349000
,最后几位都变成了00
, 这是因为,javascript的Number类型最大长度是17位,而后端返回的Long类型有19位,导致js的Number不能解析。
方案
既然不能使用js的Number接收,那么前端如何Long类型的数据呢,答案是js使用string类型接收
方案一 @JsonSerialize 注解
修改Dto的id字段,使用@JsonSerialize
注解指定类型为string。
这个方案有一个问题,就是需要程序员明确指定@JsonSerialize
, 在实际的使用过程中,程序员会很少注意到Long类型的问题,只有和前端联调的时候发现不对。
@Data
public static class GetLongValueDto{
@JsonSerialize(using= ToStringSerializer.class)
private Long id;
}
方案二 全局处理器
添加Configuration, 处理 HttpMessageConverter
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
/**
* 序列化json时,将所有的long变成string
* 因为js中得数字类型不能包含所有的java long值
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule=new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(0,jackson2HttpMessageConverter);
}
}
@Data
public static class GetLongValueDto{
private Long id;
}
发现没有@JsonSerialize
注解的信息,前端接收到的数据,也是string类型了。
与swagger集成
上面只是解决了传输时的long类型转string,但是当集成了swagger时,swagger文档描述的类型仍然是number类型的,这样在根据swagger文档生成时,会出现类型不匹配的问题
swagger 文档集成
pom或gradle
implementation group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0'
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
查看文档, 发现 GetLongValueDto 描述的id类型是 integer($int64)
swagger long类型描述为string
需要修改swagger的配置, 修改 Docket
的配置
.directModelSubstitute(Long.class, String.class)
.directModelSubstitute(long.class, String.class)
@Configuration
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())//api的配置路径
.paths(PathSelectors.any())//扫描路径选择
.build()
.directModelSubstitute(Long.class, String.class)
.directModelSubstitute(long.class, String.class)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("title") //文档标题
.description("description")//接口概述
.version("1.0") //版本号
.termsOfServiceUrl(String.format("url"))//服务的域名
//.license("LICENSE")//证书
//.licenseUrl("http://www.guangxu.com")//证书的url
.build();
}
}
查看swagger文档 , 可以看到 文档中类型已经是 string了
总结
- long类型传输到前端的两种方案:注解、修改
HttpMessageConverter
- 使用
directModelSubstitute
解决swagger文档中类型描述,避免生成代码器中描述的类型错误
关注我的公总号,一起探索新知识新技术
Spring Mvc Long类型精度丢失的更多相关文章
- Java-从Double类型精度丢失认识BigDecimal
Java-从Double类型精度丢失认识BigDecimal 参考资料 https://www.jianshu.com/p/07e3eeb90f18 https://zh.wikipedia.org/ ...
- spring mvc 形参类型
spring mvc 形参类型 1 没有占位符号的,形参的名字为参数的名称 请求路径为:organtrans/t1/t5?a=1(a为形参的的名称必须一致) @RequestMapping(" ...
- spring mvc 返回类型
spring mvc处理方法支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void 小结:1.使用 String 作为请求处理方 ...
- Spring MVC 注解类型
Spring 2.5 引入了注解 基于注解的控制器的优势 1. 一个控制器类可以处理多个动作,而一个实现了 Controller 接口的控制器只能处理一个动作 2. 基于注解的控制器的请求映射不需要存 ...
- Java-Long类型精度丢失问题
问题 今天碰到一个问题,后端需要返回给前端Long类型的id,前端收到的id会发生精度丢失. 测试代码:后端返回的值为344739147160346624 但是前端获取的值为: 解决办法 将返回的值转 ...
- Java:利用BigDecimal类巧妙处理Double类型精度丢失
目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数? 如何用BigDecimal解决double精度问题? new BigDecimal(doub ...
- C# double类型精度丢失问题
我们先看一段代码,可以在控制台程序中执行看看结果 { double d = 500; double d1 = 233.84; double d2 = d - d1; //d2=266.15999999 ...
- Spring MVC 返回类型为字符串时, 返回中文变成"?"处理
Spring controller 如下 @Controller public class SimpleController { @ResponseBody @RequestMapping(value ...
- Spring mvc @initBinder 类型转化器的使用
一.单日期格式 因为是用注解完完成的后台访问,所以必须在大配置中配置包扫描器: 1.applicactionContext.xml <?xml version="1.0" e ...
随机推荐
- 机器学习03-sklearn.LinearRegression 源码学习
在上次的代码重写中使用了sklearn.LinearRegression 类进行了线性回归之后猜测其使用的是常用的梯度下降+反向传播算法实现,所以今天来学习它的源码实现.但是在看到源码的一瞬间突然有种 ...
- K8S(18)容器环境下资源限制与jvm内存回收
K8S(18)容器环境下资源限制与jvm内存回收 目录 K8S(18)容器环境下资源限制与jvm内存回收 一.k8s中的java资源限制与可能的问题 方案1:通过JVM的Xms和Xmx参数限制 方案2 ...
- 技术分享|JavaScript的前世今生
目录 一.什么是JavaScript 二.JavaScript的功能 三.JavaScript可以做什么 四.JavaScript框架 五.HTML,CSS和JavaScript 六.JavaScri ...
- 展开说说,Spring Bean IOC、AOP 循环依赖
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 延迟满足能给你带来什么? 大学有四年时间,但几乎所有人都是临近毕业才发现找一份好工作 ...
- hdu1686 最大匹配次数 KMP
题意: 给你两个串,问你串a在串b中出现了多少次. 思路: 直接匹配,KMP时匹配到匹配串的最后一个的时候不用跳出,直接匹配就行了,最后一个'/0'不会和目标串匹配,所以经过ne ...
- android添加账户流程分析涉及漏洞修复
android修复了添加账户代码中的2处bug,retme取了很酷炫的名字launchAnyWhere.broadAnywhere(参考资料1.2).本文顺着前辈的思路学习bug的原理和利用思路. 我 ...
- POJ3687拓扑排序+贪心
题意: 给你n个求,他们的重量是1-n(并不是说1号求的重量是1...),然后给你m组关系a,b,表示a的重量小于b的重量,然后让你输出满足要求的前提下每个球的重量,要求字典序最小. 思路 ...
- Windows 怎么知道我已经连接到互联网而不是局域网? 原来当中大有文章!
Windows 怎么知道我已经连接到互联网而不是局域网? 原来当中大有文章! 转载 原文章地址:点击 2014-01-09 Windows 怎么知道我已经连接到互联网而不是局域网? 原来当中大有文章! ...
- Day004 Scanner对象
Scanner对象 作用 我们可以通过Scanner类来获取用户的输入 所属包 java.util.Scanner java 工具类下 基本语法 Scannner s=new Scanner( ...
- Matlab将数据存为文本文件
dlmwrite :将一个矩阵写到由分隔符分割的文件中. 在保存整数到文件时使用save存为ascii文件时,常常是文件里都是实型格式的数据(有小数点,和后面很多的0,看着很不方便).于是要保存此类数 ...