Apache HttpClient 读取响应乱码问题总结
Apache HttpClient 读取响应乱码问题总结
起因
最近公司产品线研发人员调整,集中兵力做战略产品,现在稳定产品迭代放慢。新的产品线当前有一个最初的版本,为了尽快了解业务,以 API 为入口,以 API 测试为手段,梳理当前版本的业务流程。
在通过 HttpClient 对 API 进行访问时,发现返回的字符串中包含的中文为乱码
环境
- JDK 1.8
- Servlet 3.0.x
- 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() 方法的处理不一致,遂查看源码,如下:

发现 setContentType 方法内部也会调用 setCharacterEncoding 方法,唯一的区别就是 setContentType 方法设置了 Content-Type 头信息
疑因3
排除掉2后,怀疑是 HttpClinet 对 ContentType 的处理有问题,并且 EntityUtils.toString(entity, Charset.forName("UTF-8"));
中的编码没有起作用。
查看其源码,如下:


从图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 读取响应乱码问题总结的更多相关文章
- HttpClient读取数据乱码的解决方案
博主是一个近十年的老书虫了,从高中那会儿就开始看网络小说.每天半天看晚上看啊,终于眼睛也近视了,成绩也下降了(....好像说远了) 最近在追辰东的<圣墟>,最近写到精彩部分了,一直等更新. ...
- Apache HttpClient 5 使用详细教程
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. 超文本传输协议(HTTP)可能是当今 ...
- HttpClient读取ASP.NET Web API错误信息的简单方法
在C#中,用HttpClient调用Web API并且通过Content.ReadAsStringAsync()读取响应内容时,如果出现500错误(InternalServerError),会得到一个 ...
- 《Apache HttpClient 4.3开发指南》
转载自:http://blog.csdn.net/chszs/article/details/16854747 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chs ...
- 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据
1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...
- Apache HttpClient之fluent API的使用
该方法为Apache HttpClient 4.5以上的版本支持,在官网有明确的说明. 对比以前的方式,其优点是代码更简洁,同时为线程安全的.仅举一个最简单的post栗子 JAR包信息: <de ...
- 1 - Apache HttpClient 简单使用
Apache HttpClient 是Apache 开源的实现Http协议的java开源库. HttpClien 是客户端的HTTP通信实现库,实现HTTP GET 和POST请求,获取响应内容. A ...
- .Net Core HttpClient处理响应压缩
前言 在上篇文章[ASP.NET Core中的响应压缩]中我们谈到了在ASP.NET Core服务端处理关于响应压缩的请求,服务端的主要工作就是根据Content-Encoding头信息判断采 ...
- 如何在Apache HttpClient中设置TLS版本
1.简介 Apache HttpClient是一个底层.轻量级的客户端HTTP库,用于与HTTP服务器进行通信. 在本教程中,我们将学习如何在使用HttpClient时配置支持的传输层安全(TLS)版 ...
随机推荐
- 【C++进阶:结构体作为叶节点初始化】
使用C++代码,表示叶节点的结构体初始化,以及使用new进行动态内存分配和赋值 #include <iostream> using namespace std; struct TreeNo ...
- 如何进行EDM邮件内容的撰写
近两个月没有来博客园更新一下博客文章了,实在惭愧,最近忙于工作,经常加班.下面来说说EDM邮件内容的撰写技巧吧,本文就跟大家交流一下自己一直以来的心得体会. EDM中很重要的一个步骤,就是邮件内容的撰 ...
- Vue知识整理8:条件、URL、点击
1.通过v-if实现对条件的判断和执行: 2.通过v-bind:href实现对url地址的绑定,其中url写在data中: 3.通过@click="click1"实现点击事件,其中 ...
- Delphi XE2 之 FireMonkey 入门(35) - 控件基础: TFmxObject: 其它
Delphi XE2 之 FireMonkey 入门(35) - 控件基础: TFmxObject: 其它 TFmxObject 增加了 TagObject.TagFloat.TagString, 算 ...
- springboot 使用外置tomcat启动
pom.xml 如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...
- Python学习之==>Excel操作
一.简介 使用Python读.写.修改excel分别需要用到xlrd.xlwt以及xlutils模块,这几个模块使用pip安装即可. 二.读excel import xlrd book = xlrd. ...
- 【Java安全】关于Java中常用加密/解密方法的实现
安全问题已经成为一个越来越重要的问题,在Java中如何对重要数据进行加密解密是本文的主要内容. 一.常用的加密/解密算法 1.Base64 严格来说Base64并不是一种加密/解密算法,而是一种编码方 ...
- 【ABAP系列】SAP ABAP 实现FTP的文件上传与下载
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 实现FTP的文 ...
- Chapter02 第三节 其他语句
2.3 其他语句 // getinfo.cpp #include <bits/stdc++.h> using namespace std; int main() { int carrots ...
- Java基础/时间日期格式
Java时间日期格式转换 一.Date转String和String转Date 参考博客:https://www.cnblogs.com/sharpest/p/7879377.html public s ...