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. Mybaits配置多个数据库操作sql环境

    mybitas可以配置sql语句适用于不同数据库下的操作,因为不同数据库sql语句可能有差别,接下来介绍如果进行操作 1.在jdbc.properprites配置驱动 jdbc.driver=com. ...

  2. db4o发布7.2,出现.NET 3.5版本,支持LINQ

    db4o发布7.2,出现.NET 3.5版本,支持LINQ   Db4Object刚刚发布了db4o的7.2beta,除了以前支持如下的平台:.NET 1.1,.NET 2.0,Mono外,现在还支持 ...

  3. 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_3 Mybatis的CRUD-修改和删除操作

    增加更新操作 更新用户的配置 测试类 删除的操作 这里的parpameterType值可以是:Integer.INTEGER.int.java.lang.Integer 讲到typeAliases标签 ...

  4. 【命令汇总】XSS payload 速查表

    日期:2019-05-15 14:06:21 作者:Bay0net 介绍:收集并且可用的一些 XSS payload,网上的速查表很多,但是测试了下很多 payload 的不可用,这里都是自己能用的 ...

  5. Linux下安装Elasticsearch6.5

    1.安装JDK8(Elastic 需要 Java 8 环境) 1)下载jdk8文件:http://www.oracle.com/technetwork/java/javase/downloads/jd ...

  6. Matlab——数值计算——单个代数方程 代数方程组

    方程求解 求解单个代数方程 MATLAB具有求解符号表达式的工具,如果表达式不是一个方程式(不含等 号),则在求解之前函数solve将表达式置成等于0. >> syms a syms b ...

  7. Matlab——图形绘制——二维平面图形

    二维平面图形 hold on ————在已画好的图形上添加新的图形 plot 是绘制一维曲线的基本函数,但在使用此函数之前,我们需先定义曲线上每一点的x 及y 座标.下例可画出一条正弦曲线: > ...

  8. 安装docker-下载加速、失败、成功安装

    前提:已装VMware虚拟机和Centos系统(具体安装包和过程可以百度) 先看这里:非root身份登录系统需要在下面的命令前加“sudo ”(sudo:代表给权限,用root登录则不需要输入) 一. ...

  9. poj1236-Tarjan算法

    题目大意: 一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校.如果A在B的表中,那么B不一定在A的表中. 现在的任务就是,给出所有 ...

  10. tcp和udp详解??

    TCP:面向连接的可靠传输 tcp规定了:传输服务必须建立连接      传输结束必须断开连接      传输数据必须保证可靠 数据的可靠性:无重复.无丢失.无失序.无差错. 建立连接(三次握手): ...