我的编程空间,编程开发者的网络收藏夹
学习永远不晚

解析Spring Mvc Long类型精度丢失问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

解析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 class="lazy" data-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 {
    
    @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类型精度丢失的详细内容,更多关于Spring Mvc Long类型的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

解析Spring Mvc Long类型精度丢失问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

js接受Long型损失精度问题怎么解决

本篇内容介绍了“js接受Long型损失精度问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、场景描述在下面这个后台管理中,当我们
2023-07-05

javascript接收long类型参数时精度丢失怎么处理

这篇文章主要介绍了javascript接收long类型参数时精度丢失怎么处理的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇javascript接收long类型参数时精度丢失怎么处理文章都会有所收获,下面我们一起
2023-06-27

SpringBoot怎么解决Long型数据转换成json格式时丢失精度问题

这篇“SpringBoot怎么解决Long型数据转换成json格式时丢失精度问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇
2023-07-02

SpringBoot分页的实现与long型id精度丢失问题的解决方案介绍

在以后的开发中,当全局唯一id的生成策略生成很长的Long型数值id之后会超过JS对Long型数据处理的能力范围,可能发生精度丢失而造成后端方法失效,我们要学会解决。分页功能虽然简单但是非常重要,对于刚接触项目的人一定要重点注意
2022-11-13

分析和解决 Golang 中数值精度丢失的问题

Golang 精度丢失问题分析与解决方法在使用 Golang 编程语言进行数学运算时,一些情况下会遇到精度丢失的问题。这种问题通常发生在浮点数运算中,特别是涉及到大数值、小数值或者需要高精度计算的情况下。本文将介绍 Golang 中精度丢
分析和解决 Golang 中数值精度丢失的问题
2024-02-24

解决页面js接受Long型损失精度问题(最新解决方案)

这篇文章主要介绍了解决页面js接受Long型损失精度问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录