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

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

疑因3

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

中的编码没有起作用。

查看其源码,如下:


图1

图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 读取响应乱码问题总结的更多相关文章

  1. HttpClient读取数据乱码的解决方案

    博主是一个近十年的老书虫了,从高中那会儿就开始看网络小说.每天半天看晚上看啊,终于眼睛也近视了,成绩也下降了(....好像说远了) 最近在追辰东的<圣墟>,最近写到精彩部分了,一直等更新. ...

  2. Apache HttpClient 5 使用详细教程

    点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. 超文本传输协议(HTTP)可能是当今 ...

  3. HttpClient读取ASP.NET Web API错误信息的简单方法

    在C#中,用HttpClient调用Web API并且通过Content.ReadAsStringAsync()读取响应内容时,如果出现500错误(InternalServerError),会得到一个 ...

  4. 《Apache HttpClient 4.3开发指南》

    转载自:http://blog.csdn.net/chszs/article/details/16854747 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chs ...

  5. 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据

    1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...

  6. Apache HttpClient之fluent API的使用

    该方法为Apache HttpClient 4.5以上的版本支持,在官网有明确的说明. 对比以前的方式,其优点是代码更简洁,同时为线程安全的.仅举一个最简单的post栗子 JAR包信息: <de ...

  7. 1 - Apache HttpClient 简单使用

    Apache HttpClient 是Apache 开源的实现Http协议的java开源库. HttpClien 是客户端的HTTP通信实现库,实现HTTP GET 和POST请求,获取响应内容. A ...

  8. .Net Core HttpClient处理响应压缩

    前言     在上篇文章[ASP.NET Core中的响应压缩]中我们谈到了在ASP.NET Core服务端处理关于响应压缩的请求,服务端的主要工作就是根据Content-Encoding头信息判断采 ...

  9. 如何在Apache HttpClient中设置TLS版本

    1.简介 Apache HttpClient是一个底层.轻量级的客户端HTTP库,用于与HTTP服务器进行通信. 在本教程中,我们将学习如何在使用HttpClient时配置支持的传输层安全(TLS)版 ...

随机推荐

  1. 【C++进阶:结构体作为叶节点初始化】

    使用C++代码,表示叶节点的结构体初始化,以及使用new进行动态内存分配和赋值 #include <iostream> using namespace std; struct TreeNo ...

  2. 如何进行EDM邮件内容的撰写

    近两个月没有来博客园更新一下博客文章了,实在惭愧,最近忙于工作,经常加班.下面来说说EDM邮件内容的撰写技巧吧,本文就跟大家交流一下自己一直以来的心得体会. EDM中很重要的一个步骤,就是邮件内容的撰 ...

  3. Vue知识整理8:条件、URL、点击

    1.通过v-if实现对条件的判断和执行: 2.通过v-bind:href实现对url地址的绑定,其中url写在data中: 3.通过@click="click1"实现点击事件,其中 ...

  4. Delphi XE2 之 FireMonkey 入门(35) - 控件基础: TFmxObject: 其它

    Delphi XE2 之 FireMonkey 入门(35) - 控件基础: TFmxObject: 其它 TFmxObject 增加了 TagObject.TagFloat.TagString, 算 ...

  5. springboot 使用外置tomcat启动

    pom.xml  如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  6. Python学习之==>Excel操作

    一.简介 使用Python读.写.修改excel分别需要用到xlrd.xlwt以及xlutils模块,这几个模块使用pip安装即可. 二.读excel import xlrd book = xlrd. ...

  7. 【Java安全】关于Java中常用加密/解密方法的实现

    安全问题已经成为一个越来越重要的问题,在Java中如何对重要数据进行加密解密是本文的主要内容. 一.常用的加密/解密算法 1.Base64 严格来说Base64并不是一种加密/解密算法,而是一种编码方 ...

  8. 【ABAP系列】SAP ABAP 实现FTP的文件上传与下载

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 实现FTP的文 ...

  9. Chapter02 第三节 其他语句

    2.3 其他语句 // getinfo.cpp #include <bits/stdc++.h> using namespace std; int main() { int carrots ...

  10. Java基础/时间日期格式

    Java时间日期格式转换 一.Date转String和String转Date 参考博客:https://www.cnblogs.com/sharpest/p/7879377.html public s ...