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

先说下背景:该项目用的是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. 分享:C语言大礼包(PDF)

    链接:https://pan.baidu.com/s/1xpOcT1gRhdumV5MlkC4AFQ 提取码:4kh6

  2. C#LeetCode刷题之#53-最大子序和(Maximum Subarray)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4012 访问. 给定一个整数数组 nums ,找到一个具有最大和的 ...

  3. Eclipse怎么调整字体大小和主题

    调整字体 哈哈哈哈哈 ( ̄▽ ̄),直接Ctrl + -/+号,....在英文输入法状态. 或者,你想更细致的调整字体类型,可以在Winodw -> Preferences中调整: 换主题 你可以 ...

  4. 【ZJOI2007】棋盘制作 - 悬线法

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个 \(8 \times 8\) 大小的黑白相间的方阵,对应八八六十四卦 ...

  5. 遗传算法框架-基于java jenetics库实现

    本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法. GA算法的逻辑还是贴下: 好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用 ...

  6. OAuth2.0分布式系统环境搭建

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 介绍 OAuth(开放授权)是一 ...

  7. 第4章 SparkSQL数据源

    第4章 SparkSQL数据源 4.1 通用加载/保存方法 4.1.1 手动指定选项 Spark SQL的DataFrame接口支持多种数据源的操作.一个DataFrame可以进行RDDs方式的操作, ...

  8. ucore lab2

    CPU在如下时刻会检查特权级 访问数据段 访问页 进入中断服务例程(ISR) RPL位于段寄存器 DS ES FS GS CPL位于CS SS DPL位于段描述符表/门描述符 访问门时: CPL< ...

  9. selenium定位方法实例

    selenium定位方法实例 首先打开浏览器输入微博的网址,将网页最大化,等待3秒 from selenium import webdriver import time driver = webdri ...

  10. classmethod与staticmethod

    1.classmethod   @classmethod # 把一个对象绑定的方法 修改成一个 类方法第一,在方法中仍然可以引用类中的静态变量第二,可以不用实例化对象,就直接用类名在外部调用这个方法什 ...