背景

在使用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了

总结

  1. long类型传输到前端的两种方案:注解、修改HttpMessageConverter
  2. 使用directModelSubstitute解决swagger文档中类型描述,避免生成代码器中描述的类型错误

关注我的公总号,一起探索新知识新技术

Spring Mvc Long类型精度丢失的更多相关文章

  1. Java-从Double类型精度丢失认识BigDecimal

    Java-从Double类型精度丢失认识BigDecimal 参考资料 https://www.jianshu.com/p/07e3eeb90f18 https://zh.wikipedia.org/ ...

  2. spring mvc 形参类型

    spring mvc 形参类型 1 没有占位符号的,形参的名字为参数的名称 请求路径为:organtrans/t1/t5?a=1(a为形参的的名称必须一致) @RequestMapping(" ...

  3. spring mvc 返回类型

    spring mvc处理方法支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void 小结:1.使用 String 作为请求处理方 ...

  4. Spring MVC 注解类型

    Spring 2.5 引入了注解 基于注解的控制器的优势 1. 一个控制器类可以处理多个动作,而一个实现了 Controller 接口的控制器只能处理一个动作 2. 基于注解的控制器的请求映射不需要存 ...

  5. Java-Long类型精度丢失问题

    问题 今天碰到一个问题,后端需要返回给前端Long类型的id,前端收到的id会发生精度丢失. 测试代码:后端返回的值为344739147160346624 但是前端获取的值为: 解决办法 将返回的值转 ...

  6. Java:利用BigDecimal类巧妙处理Double类型精度丢失

    目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数? 如何用BigDecimal解决double精度问题? new BigDecimal(doub ...

  7. C# double类型精度丢失问题

    我们先看一段代码,可以在控制台程序中执行看看结果 { double d = 500; double d1 = 233.84; double d2 = d - d1; //d2=266.15999999 ...

  8. Spring MVC 返回类型为字符串时, 返回中文变成"?"处理

    Spring controller 如下 @Controller public class SimpleController { @ResponseBody @RequestMapping(value ...

  9. Spring mvc @initBinder 类型转化器的使用

    一.单日期格式 因为是用注解完完成的后台访问,所以必须在大配置中配置包扫描器: 1.applicactionContext.xml <?xml version="1.0" e ...

随机推荐

  1. Day11_55_在Map集合中使用泛型

    在Map集合中使用泛型 ``` import java.util.HashMap; import java.util.Iterator; import java.util.Map; import ja ...

  2. 【pytest官方文档】解读fixtures - 10. fixture有效性、跨文件共享fixtures

    一.fixture有效性 fixture有效性,说白了就是fixture函数只有在它定义的使用范围内,才可以被请求到.比如,在类里面定义了一个fixture, 那么就只能是这个类中的测试函数才可以请求 ...

  3. ambari介绍及安装

    Ambari简介 Ambari概述 Apache Ambari是一种基于Web的工具,支持Apache Hadoop集群的创建.管理和监控.Ambari已支持大多数Hadoop组件,包括HDFS.Ma ...

  4. c协程库libco几点体会

    https://www.cnblogs.com/dearplain/p/9820913.html 这里说的是Tencent开源的libco. libco的用途和依赖 主要还是c/c++服务端,相比li ...

  5. 为什么有时博客中的代码复制进自己的VS中报错

    昨天写代码时遇到一个问题,我搜了一篇博客,然后复制到我的WPF中, 然后,全报错(当时快给我气死了,一篇有一篇的不能用,试了一次又一次,时间全浪费在这上面了,没打游戏,做的东西也没出来) 问题原因: ...

  6. 脱壳——修复加密IAT

    脱壳--修复加密IAT 对两个练手程序进行脱壳修复加密IAT(其实是一个程序,只是用了几种不同的加壳方式) 第一个程序 Aspack.exe 下载链接:https://download.csdn.ne ...

  7. 2- 计算机的组成以及VMware使用

    计算机的组成: 硬件: 处理器(CPU):I3 I5 I7 运行内存RAM(存储数据) 容量(字节为单位) 主板(总线设备) 输入输出设备(显示屏,键盘,鼠标,触目屏) 外部存储设备(硬盘,U盘,TF ...

  8. PHP生成随机数的几种方法

    第一种方法用mt_rand() function GetRandStr($length){ $str='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV ...

  9. Android敲诈者病毒“安卓性能激活”分析(2015年9月版)

    一.情况简介 前几天分析了论坛里的一个Android敲诈者病毒,感觉还是很有收获,后面有空多研究研究Android病毒.说句题外话, 根据前面分析的Android敲诈者病毒的隐藏手法,应该可以实现&q ...

  10. Average Score39届亚洲赛牡丹江站A题

    题意:       A班有n个人,B班有m个人,然后现在给你n-1个A班人的成绩,和m个B班人的成绩,然后题目要求求出A班剩下的没给成绩那个人的成绩范围,要求是这个人从A班转到B班后能使A,B的平均分 ...