解析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类型精度丢失的详细内容,更多关于Spring Mvc Long类型的资料请关注我们其它相关文章!

(0)

相关推荐

  • SpringBoot全局配置long转String丢失精度问题解决方案

    web项目中,前端JS使用Java后端传过来的Long/long会丢失精度. 后端将返回的数据改为String使用即可 第一种 自己建个配置类 extends WebMvcConfigurerAdapter 已经被弃用,直接实现WebMvcConfigurer该接口就行了 @EnableWebMvc @Configuration public class WebDataConvertConfig implements WebMvcConfigurer { public void configur

  • 解析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() @Re

  • Java用BigDecimal类解决Double类型精度丢失的问题

    本篇要点 简单描述浮点数十进制转二进制精度丢失的原因. 介绍几种创建BigDecimal方式的区别. 整理了高精度计算的工具类. 学习了阿里巴巴Java开发手册关于BigDecimal比较相等的规定. 经典问题:浮点数精度丢失 精度丢失的问题是在其他计算机语言中也都会出现,float和double类型的数据在执行二进制浮点运算的时候,并没有提供完全精确的结果.产生误差不在于数的大小,而是因为数的精度. 关于浮点数存储精度丢失的问题,话题过于庞大,感兴趣的同学可以自行搜索一下:[解惑]剖析floa

  • 通过原理解析Spring mvc的内置编码过滤器

    前言 在Spring mvc框架中是如何解决从页面传来的字符串的编码问题的呢? 下面我们来看看Spring框架给我们提供过滤器CharacterEncodingFilter,话不多说了,来一起看看详细的介绍吧. web.xml 中 添加如下配置: <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.Ch

  • iOS浮点类型精度问题的原因与解决办法

    目录 前言 如何解决浮点型精度问题 四舍五入处理 更优的解决方案 精度丢失的原因 浮点类型的存储方式 有效位数 指数的存储方式:移位存储 double类型 总结:输出结果丢失精度原因 前言 相信不少人(其实我觉得应该是每个人)都遇到过一个问题,那就是当服务端返回的JSON数据中出现了小数时,客户端用CGFloat去解析时总是会出现精度丢失的问题,尤其当遇到敏感数据时,这种精度丢失是完全不能被容忍的,本文会从简单的解决方案和原理出发,一起带大家回顾一下这个其实大家以前都学过但是都忘的差不多了的小问

  • Spring MVC文件上传大小和类型限制以及超大文件上传bug问题

    在上一篇文章中,主要介绍了Spirng MVC环境下的正常情况下文件上传功能实现.在实际开发的时候,还会涉及到上传文件大小和类型的限制,接下来就会对Spirng MVC环境下文件上传大小和类型的限制进行介绍,还会讲解到文件上传大小tomcat服务器bug问题及解决方案. 一.文件上传大小限制 这里还是接着上篇文章先介绍Spring MVC下的文件上传大小限制,文件上传大小的限制在springmvc-config.xml中配置文件解析器CommonsMultipartResolver时即可配置,示

  • 自定义spring mvc的json视图实现思路解析

    场景 我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范, 前端(安卓,Ios,web前端)和后端进行了数据的格式规范的讨论,确定了json的数据格式: { "code":"200", "data":{"":""}, "message":"处理成功" } { "code":"300", "

  • spring MVC中接口参数解析的过程详解

    前言 前天工作中遇到了这样一个问题,我在接口的参数封装了一个pojo,这是很常见的,当参数一多,惯性的思维就是封装一个pojo.那么在参数前有很多注解可以添加,比如:@requestParam,@requestBody,@pathvariable等.我的理解是这样的,首先我先申明,我并是没有看过源码,只是凭经验理解.@requestParam试用于get请求,参数在http的header中的URL上,具体放在?后面以key=value的形式存在.@requestBody适用于post请求中参数在

  • Spring MVC处理方法返回值过程解析

    这篇文章主要介绍了Spring MVC处理方法返回值过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 对于Spring MVC处理方法支持支持一系列的返回方式: (1)ModelAndView (2)Model (3)ModelMap (4)Map (5)View (6)String (7)Void (8)Object 一,ModelAndView @RequestMapping("/threadRequest*") publi

  • Spring mvc Controller和RestFul原理解析

    控制器Controller 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现. 控制器负责解析用户的请求并将其转换为一个模型. 在Spring MVC中一个控制器类可以包含多个方法 在Spring MVC中,对于Controller的配置方式有很多种 实现Controller接口 Controller是一个接口,在org.springframework.web.servlet.mvc包下,接口中只有一个方法: //实现该接口的类获得控制器功能 public interfa

  • 基于Mock测试Spring MVC接口过程解析

    1. 前言 在Java开发中接触的开发者大多数不太注重对接口的测试,结果在联调对接中出现各种问题.也有的使用Postman等工具进行测试,虽然在使用上没有什么问题,如果接口增加了权限测试起来就比较恶心了.所以建议在单元测试中测试接口,保证在交付前先自测接口的健壮性.今天就来分享一下胖哥在开发中是如何对Spring MVC接口进行测试的. 在开始前请务必确认添加了Spring Boot Test相关的组件,在最新的版本中应该包含以下依赖: <dependency> <groupId>

随机推荐