最近开始对APP上的Crash进行对应,发现有好多常见的问题,同一个问题在多个APP都类似的出现了,这里记录下这些常见的错误。

crash Log:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: com.google.gson.stream.MalformedJsonException: Unterminated string at line 1 column 425727 path $.shops[631].lineup; nested exception is com.google.gson.ad: com.google.gson.stream.MalformedJsonException: Unterminated string at line 1 column 425727 path $.shops[631].lineup
at 包名.k.readInternal(SourceFile:75)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(SourceFile:147)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(SourceFile:76)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(SourceFile:655)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(SourceFile:641)
at org.springframework.web.client.RestTemplate.doExecute(SourceFile:484)
at org.springframework.web.client.RestTemplate.execute(SourceFile:439)
at org.springframework.web.client.RestTemplate.exchange(SourceFile:415)

根据错误log的意思,应该是服务器(php开发)返回了非正常的json格式错误信息导致app崩溃。

项目背景:

项目是使用AA框架开发的,Api请求使用的是SpringRestTemplate,使用Gson进行json与Bean的转换

为了解决Gson在Android6.0上的bug,自定义了一个GsonConverter,继承自GsonHttpMessageConverter。在数据转换时添加了log,主要代码如下:

 @Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
String str = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), getCharset(inputMessage.getHeaders())));
LogUtil.d("in =" + str);
try {
Type typeOfT = getType(); if (typeOfT != null) {
return this.gson.fromJson(str, typeOfT);
} else {
return this.gson.fromJson(str, clazz);
}
} catch (JsonSyntaxException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (JsonIOException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (Exception ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
}
}

然后就是AA中Rest的配置了,将自定义的GsonConverter配置到Rest上。

在每个请求中都设置了RestErrorHandler,单纯的log出数据,并没有业务逻辑

mClient.setRestErrorHandler(handler);
@Override
public void onRestClientExceptionThrown(RestClientException e) {
LogUtil.e(e);
}

根据CrashLog,定位到问题是Api返回的数据转换成Bean出错导致的,代码定位到了GsonConverter.readInternal方法,通常来说方法上已经声明了错误类型了,按照业务逻辑抛出指定的错误类型不应该导致App崩溃,应该是回调RestErrorHandler的方法才对的。但是根据实际测试下来和猜想的还是有很大的区别。

然后抽取一个Api,代码如下:


ResponseEntity<CheckVersionResponse> entity = apiHelper.checkVersion(); if (null == entity || !entity.hasBody()) {
return;
}

如果在GsonConverter.readInternal中抛出异常,则App崩溃。如果在以上代码中添加TryCatch,则可以捕获到异常。这个就好奇了,怎么是直接抛出异常,而不会回调异常处理接口。如果是这么修改的话,整个系统几十个接口都需要修改,工程量太大而且太傻。

解决办法:

既然抛出异常会导致崩溃,那么当Api转换错误时,数据返回null不就可以了。修改后的代码:

 @Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
String str = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), getCharset(inputMessage.getHeaders())));
LogUtil.d("in =" + str);
try {
Type typeOfT = getType(); if (typeOfT != null) {
return this.gson.fromJson(str, typeOfT);
} else {
return this.gson.fromJson(str, clazz);
}
} catch (JsonSyntaxException ex) {
LogUtil.e("Could not read JSON: " + ex.getMessage(), ex);
// throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (JsonIOException ex) {
LogUtil.e("Could not read JSON: " + ex.getMessage(), ex);
// throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (Exception ex) {
LogUtil.e("Could not read JSON: " + ex.getMessage(), ex);
// throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
}
return null;
}

原因分析:

解决办法找到了,深究下定位个原因,AA框架自动生成的ApiClient源码:


@Override
public ResponseEntity<CheckVersionResponse> checkVersion(Map<String, Object> params) {
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<Map<String, Object>>(params);
try {
return restTemplate.exchange(rootUrl.concat("/checkVersion/"), HttpMethod.POST, requestEntity, CheckVersionResponse.class);
} catch (RestClientException e) {
if (restErrorHandler!= null) {
restErrorHandler.onRestClientExceptionThrown(e);
return null;
} else {
throw e;
}
}
}

从这里可以看出,只有RestClientException类型才会回调异常回调接口,其他的错误只会直接抛出。

然而HttpMessageNotReadableException不是RestClientException类型的,所以异常就直接抛出,没有被捕获当然就导致APP崩溃了。

Crash-fix-2:org.springframework.http.converter.HttpMessageNotReadableException的更多相关文章

  1. Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public xxxxxxxx.

    最近在使用 springBoot开发的时候, 使用PostMan访问接口,  返回一个 404 ,  后台报一个 warn : Failed to read HTTP message: org.spr ...

  2. org.springframework.http.converter.HttpMessageNotReadableException

    发起请求报错:org.springframework.http.converter.HttpMessageNotReadableException 查看请求头: application/json 所以 ...

  3. DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

    客户端当发送空的json字符串时,请求RestController时,报错: DefaultHandlerExceptionResolver : Failed to read HTTP message ...

  4. 异常:org.springframework.http.converter.HttpMessageNotReadableException

    spring(springboot.springmvc)出现标题的异常一般是由于controller的入参失败引起的. 介绍下常规入参的两种格式: ,这种方式的入参主要是接受key-value的参数, ...

  5. Spring 4.x org.springframework.http.converter.json.MappingJacksonHttpMessageConverter ClassNotFoundException:

    Spring 4.x The first major version of Jackson is no longer supported in Spring 4. The class you want ...

  6. SSM框架搭建java.lang.ClassNotFoundException: org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

    在搭建 spring springMVC Mybatis 时候出错 将org.springframework.http.converter.json.MappingJacksonHttpMessage ...

  7. Not found org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

    原因spring3跟spring4的jackson不一样. 解决方案: 1)spring3.x是org.springframework.http.converter.json.MappingJacks ...

  8. Springmvc 中org.springframework.http.converter.json.MappingJackson2HttpMessageConverter依赖jackson包

    1,问题详情:Spring使用4.3.5.Release版本后 在SpringMvc配置文件中配置json 解析器后出现报错信息 [org.springframework.web.context.Co ...

  9. java.lang.ClassNotFoundException: org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

    原因是Spring 3.x 和4.X处理JSON的一个类不一样,而这个东西又配置在xml文件中,所以编译时又无法发现 spring3.x是org.springframework.http.conver ...

随机推荐

  1. 高德地图首席科学家任小枫QA答疑汇总丨视觉+地图技术有哪些新玩法?

    上周,阿里巴巴高德地图首席科学家任小枫在#大咖学长云对话#的在线直播活动上就计算机视觉相关技术发展以及在地图出行领域的应用与大家做技术交流,直播间互动火爆,尤其在QA环节,学弟学妹们纷纷就感兴趣的视觉 ...

  2. Jetson AGX Xavier更换apt-get源

    使用apt-get安装时,会很慢,更换了国内的源后,就可以解决这个问题了. 1. 备份sources.list文件 sudo cp /etc/apt/sources.list /etc/apt/sou ...

  3. beego rel/reverse

    用户可以发布多个文章 对用户来说是一对多 对文章来说是多对一 用户是主表 文章是用户的从表 rel用在从表中,给主表结构体设置主键,也就是文章表对应用户表的外键 reverse用在主表中,指定主表与从 ...

  4. 安装宝塔检测到系统已存在Apache,请使用纯净安装

    执行命令 停止服务 net stop Apache2.4 删除服务 sc delete apache

  5. Qt5 escape spaces in path

    There are two possible ways. You can either use escaped quotes (inserting the string between quotes) ...

  6. NFS共享设置

    一.安装所需要的软件环境[root@fengling ~]# yum -y install rpcbind nfs-utils二.创建共享目录mkdir /web三.启动服务[root@fenglin ...

  7. chrome清除缓存、不使用缓存而刷新快捷键

    Ctrl+Shift+Del  清除Google浏览器缓存的快捷键 Ctrl+Shift+R  重新加载当前网页而不使用缓存内容 转载于:https://www.cnblogs.com/JAVA-ST ...

  8. OpenCV的安装和使用

    @ windows系统 (环境:VS2013) 下载安装opencv.exe: VS2013下“项目”->“属性页”->“配置属性”-> “VC++目录”: 包含目录 - ..\op ...

  9. Codeforces Round #622 (Div. 2) 1313 A

    Tired of boring office work, Denis decided to open a fast food restaurant. On the first day he made ...

  10. 题目分享T

    题意:蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n),并保证所有的长度都是非负整数(即:可 能存在长度为0的蚯蚓).每一秒,神刀手会 ...