Apache HttpClient 读取响应乱码问题总结

摘要:
排除可疑原因2后,怀疑setContentType()方法和setCharacterEncoding()方法的处理不一致,请按如下方式检查源代码:enterdescriptionhere发现setCharacterEncode方法也被setContentType方法内部调用。唯一的区别是setContentType方法设置ContentType头信息。排除了可疑原因3后,怀疑HttpClinet在处理ContentType和EntityUtils toString时存在问题;中的编码不起作用。因此,当服务器没有显式设置ContentType时,Httpclient将使用ISO-8859-1编码格式来编码响应数据,而不是显式传入的UTF-8编码,因此中文将被乱码。
Apache HttpClient 读取响应乱码问题总结
setCharacterEncoding  Content-Type  HttpClient 

起因

最近公司产品线研发人员调整,集中兵力做战略产品,现在稳定产品迭代放慢。新的产品线当前有一个最初的版本,为了尽快了解业务,以 API 为入口,以 API 测试为手段,梳理当前版本的业务流程。

在通过 HttpClient 对 API 进行访问时,发现返回的字符串中包含的中文为乱码

环境

  1. JDK 1.8
  2. Servlet 3.0.x
  3. HttpClient 4.2.1

排查

疑因1

由于我们对 HttpClient 进行了再次封装,封装中使用 UTF-8 对响应数据进行编码,之前其它产品线也都使用此 Jar 进行后端 Http API 访问,均未出现乱码的情况,所以初步怀疑是服务没有设置响应编码为 UTF-8
HttpClient 封装代码如下:

HttpEntity entity = response.getEntity();
if (code >= 200 && code < 400) {
    return EntityUtils.toString(entity, Charset.forName("UTF-8"));
} else {
    EntityUtils.consume(entity);
    throw new IllegalArgumentException("请检查连接是否正确,http return code=" + code);
}

查看服务端代码,发现设置了响应的字符编码

response.setCharacterEncoding("UTF-8");

这样服务端编码与客户端编码都是 UTF-8,理论上不应出现乱码的情况。
继续看代码,发现后端代码没有设置响应的 Content-Type,加上如下代码:

response.setContentType("application/json;charset=utf-8");

再次进行测试,发现中文显示正常。

疑因2

排除掉疑因1后,怀疑 setContentType() 方法和 setCharacterEncoding() 方法的处理不一致,遂查看源码,如下:

enter description here
enter description here

发现 setContentType 方法内部也会调用 setCharacterEncoding 方法,唯一的区别就是 setContentType 方法设置了 Content-Type 头信息

疑因3

排除掉2后,怀疑是 HttpClinet 对 ContentType 的处理有问题,并且 EntityUtils.toString(entity, Charset.forName("UTF-8"));
中的编码没有起作用。

查看其源码,如下:

图1
图1

图2
图2

从图1中可以看出来,如果没有设置响应 ContentType,它会设置一个默认的 ContentType,从图2中可以看来,设置的默认
Content-Type : text/plain;Charset=ISO-8859-1
Httpclient 会优先使用 ContentType 的编码,只在 ContentType 编码取不到的情况下,才会使用传入的编码(defaultCharset),而默认的 ContentType 始终带有编码(ISO-8859-1)。

所以,当服务端未显式设置 ContentType 时,Httpclient 会使用 ISO-8859-1 编码格式对响应数据进行编码,而不是显式传入的 UTF-8 编码,所以中文会出现乱码。

总结

问题找到原因了,就好办了。
我们只需要显示设置服务端响应 Content-Type 即可,而且这样可以避免通过浏览器访问接口时出现乱码,兼容性更好。

个人认为这是 HttpClient 的一个 bug ,本想给官方提个 issue,但没找到提 Bug 的入口(笑哭),如有人知道,烦请告知,不胜感激!

免责声明:文章转载自《Apache HttpClient 读取响应乱码问题总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇python xlwings API接口之NumberFormat用法【ITOO 1】将List数据导出Excel表下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ansible playbooks

Playbook是Ansible的配置,部署和编排语言。 他们可以描述您希望远程系统执行的策略,或一般IT流程中的一组步骤。 如果Ansible modules是您workshop的工具,则playbooks是您的说明手册,您的主机inventory是您的原材料。 在基本层面上,可以使用playbooks来管理远程机器的配置和部署。 在更高级别,他们可以对...

查看当前linux有多少http连接数

已采纳 1、查看apache当前并发访问数:    #对比httpd.conf中MaxClients的数字差距多少。netstat -an | grep ESTABLISHED | wc -l2、查看httpd进程数(即prefork模式下Apache能够处理的并发请求数):ps aux|grep httpd|wc -l3、可以使用如下参数查看数据    ...

mybatis 报错:Caused by: java.lang.NumberFormatException: For input string

mybatis的if标签之前总是使用是否为空,今天要用到字符串比较的时候遇到了困难,倒腾半天,才在一个论坛上找到解决方法。笔记一下,如下: 转自:https://code.google.com/p/mybatis/issues/detail?id=262 错误描述: <select id="sltTreatment" resultType="com....

CC攻击:linux-Apache的ab工具

./ab -n 22 地址 压力测试工具ab(apache自带) http://www.jb51.net/article/59469.htm 目录:一般在apache安装目录下/usr/local/apache/bin/ ab 启动:./ab -n在测试会话中所执行的请求个数。默认时,仅执行一个请求。 -c一次产生的请求个数。默认是一次一个。 -t测试所...

【转】maven常用插件介绍

我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如maven- compiler-plugin的compile目标用来编译位于src/main/j...

Django用Apache和mod_wsgi部署

背景 最近写了一个Django在windows上运行,但是用的vbs命令,导致在后台运行的时候,必须用户登录才可以运行,还有就是登录之后,有其他进程可能被干掉。 Set ws = CreateObject("Wscript.Shell") ws.run "cmd /c D:\xxd\run.bat",vbhide ` bat 内容 C:\Python3...