最近项目中遇到了一个问题,费好大劲才发现问题所在,并且修复了问题,下面分享一下这个问题的定位和修复的新路旅程。

先说下背景:该项目用的是SpringBoot框架,主要功能为对外提供一些Restful API,使用的Servlet容器是默认的Tomcat,Json解析工具是默认的Jackson,通过@RequestBody注解来解析body。

再说下问题:用户通过https方法调用POST方法的接口,会偶现Jackson解析Json体失败的问题。这个问题比较离奇,同样的数据,同样的接口,有时候会发生解析失败。大概成功10+次会失败一次的频率。报错信息如下:

JSON parse error: Unexpected end-of-input: expected close marker for Object (start marker at [Source: (PushbackInputStream); line: 1, column: 1]);
nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: expected close marker for Object (start marker at
[Source: (PushbackInputStream); line: 1, column: 1])\n at [Source: (PushbackInputStream); line: 1, column: 3]。

值得一提的是,line和column的值每次都会不一样。

由于服务部署在公有云上,依赖的周边服务有不少,所以要先进行问题的定界。

  1. 不通过公有云注册的API,而是直接通过公网IP:PORT的形式调用,问题复现。排除APIG服务问题。
  2. 进入容器节点,直接调用容器内的pod ip,问题复现。排除k8s或者CCE服务的问题。
  3. 至此,已经能排除公有云服务的问题,可以专注定位是否是框架或者实现有问题。

接下来观察一下报错信息,显然是解析body体出了问题,看起来像是body体不完整导致的,而且每次提示的line和column值都不一样,感觉是body体在哪里被截断了。那很自然的会做以下猜测:

  1. body体本身不合法。不再赘述,推荐一个在线平台 bejson
  2. https请求对body内容做了拦截。查看请求头中是否包含Content-Length,如果包含的话,可能就是这个值有问题,把这个Content-Length从请求头中删除掉
  3. body体被spring框架拦截。
  4. body体被spring内的tomcat拦截。
--server.max-http-header-size=8192000
--server.tomcat.max-http-post-size=-1
--spring.server.tomcat.max-http-header-size=52428800
--spring.server.tomcat.max-http-post-size=-1
--spring.http.multipart.max-file-size=1000m
--spring.http.multipart.max-request-size=1000m

spring和tomcat的配置有很多,找了很多参数,都没有解决问题,行吧,只能打断点看了。

经过测试本地无法复现,那就只能对远程服务器上的deployment进行远程debug。基于IDEA进行springboot工程的远程调试方法见我之前的blog:基于IDEA对springboot做远程调试

根据日志打出来的栈信息,不难找到是在AbstractJackson2HttpMessageConverter. readJavaType方法报的错,这个Converter方法其实就是spring-web的http消息转换器,

readJavaType方法定义:

private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException

报错信息显示在这一行:

return this.objectMapper.readValue(inputMessage.getBody(), javaType)

这里调用了Jackson的readValue方法对message这个流进行解析,那我们从这里开始单步调试,下一步应该进到jackson的readValue方法了,此时通过ctrl+左键进入这个方法,

发现jackson-core的版本为2.11.2,而报错的栈信息中jackson-core版本为2.10.2,两边的版本不一致?

由于spring-web版本是spring starter中指定的,带着疑问,我尝试着把starter的版本升级到最新的2.3.0.RELEASE,对环境上的应用进行了升级,

问题不再复现…好吧,终于解决。之前用的starter是2.2.5.RELEASE,有可能是仓库中的该版本包有问题,亦或是这个版本下spring-web的版本就是有BUG,这个不得而知了…

【问题】【SpringBoot】记一次springboot框架下用jackson解析RequestBody失败的问题的更多相关文章

  1. SpringBoot项目框架下ThreadPoolExecutor线程池+Queue缓冲队列实现高并发中进行下单业务

    主要是自己在项目中(中小型项目) 有支付下单业务(只是办理VIP,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...

  2. 基于Maven的Springboot+Mybatis+Druid+Swagger2+mybatis-generator框架环境搭建

    基于Maven的Springboot+Mybatis+Druid+Swagger2+mybatis-generator框架环境搭建 前言 最近做回后台开发,重新抓起以前学过的SSM(Spring+Sp ...

  3. 【spring-boot】快速构建spring-boot微框架

    spring-boot是一个快速构建环境的一套框架,其设计理念是尽可能的减少xml的配置,用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义 ...

  4. 记一次SpringBoot 开发中所遇到的坑和解决方法

    记一次SpringBoot 开发中所遇到的坑和解决方法 mybatis返回Integer为0,自动转型出现空指针异常 当我们使用Integer去接受数据库中表的数据,如果返回的数据中为0,那么Inte ...

  5. JAVAEE——SpringBoot日志篇:日志框架SLF4j、日志配置、日志使用、切换日志框架

    Spring Boot 日志篇 1.日志框架(故事引入) 小张:开发一个大型系统: ​ 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件 ...

  6. 基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇

    基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇 前提 最近对网络编程方面比较有兴趣,在微服务实践上也用到了相对主流的RPC框架如Spring Cloud Gateway底层也切换 ...

  7. 基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇

    前提 前置文章: Github Page:<基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> Coding Page:<基于Netty和SpringBoot实现 ...

  8. 基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇

    前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> 前 ...

  9. 记一次springboot项目,maven引发的悲剧(Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletCont)

    maven下载大的项目的时候,jar包下载出错是常见的, 但是这种情况经常能看到,如java.lang.ClassNotFoundException这样的提示, 所以一直以来也觉得maven下载jar ...

随机推荐

  1. 一道 3 行代码的 Python面试题,我懵逼了一天

    有意思的题目 题目:写出下面程序运行结果 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的 ...

  2. js 自定义属性操作

    自定义属性操作     element.属性 获取内置属性值     element.getAttribute("属性") 我们自己添加的属性叫自定义属性     element. ...

  3. 【Gin-API系列】配置文件和数据库操作(三)

    我们前面已经实现了API的基础版本,能对参数校验和返回指定数据,这一章,我们将对主机和交换机进行建模,存入数据库. 考虑到数据库安装和使用的简便性,我们采用文档存储结构的MongoDB数据库. Mon ...

  4. 栈及其简单应用(二)(python代码)

    一.括号判定 前一篇文章我们介绍了栈的简单应用中,关于括号的判定,但那只是一种括号的判定,下面我们来介绍多种括号混合使用时,如何判断括号左右一一对应. 比如“{}{(}(][”这种情况,需要对一种括号 ...

  5. Homekit_人体感应器

    前置需求: 苹果手机一台 Homekit人体感应一台 USB供电线一根 这款产品内置人体红外感应器,使用圆环设计,增大了其接触面积,使感应变得更加灵敏,重量轻,方便将其粘贴到墙上,同时支持二次开发,如 ...

  6. JS的数据属性和访问器属性

    ECMA-262第5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征.ECMA-262定义这些特性是为了实现javascript引擎用的,因此在javasc ...

  7. 题解 P1407

    建图方式:旧关系女人连男人,现关系男人连女人(当然,反过来也可以) 原因可以这样考虑: 如果一个男的把女的绿了,那么这个女人就会去找一个她曾经交往过的男人,也就是在这种情况下,某种"影响&q ...

  8. DB2数据库错误代码大全

    SQLCode SQLState 状态说明 000 00000 SQL语句成功完成 01xxx XXX SQL语句成功完成,但是有警告 +012 01545 未限定的列名被解释为一个有相互关系的引用 ...

  9. axios 常用的几个方法

    Vue推荐使用axios 发送网络请求:最近重新开始做Vue项目,重新回归一下.从axios的几个方法开始吧. 1. 安装: 既然是Vue项目,我还是选择常用的npm的方式 $ npm install ...

  10. Fiddler+模拟器+APP抓包HTTPS 为什么有时候抓不到?

    抓包的原理是什么? 代理 客户端请求 -> 经过代理 -> 到达服务端 服务端返回 -> 经过代理 -> 到达客户端 任何Https的App都能抓到包么? Android7.0 ...