zoukankan      html  css  js  c++  java
  • Apache HttpClient 读取响应乱码问题总结

    Apache 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 的入口(笑哭),如有人知道,烦请告知,不胜感激!

  • 相关阅读:
    HTML2
    HTML1
    MySQL进阶part4
    pymysql模块
    MySQL进阶part3
    MySQL进阶part2
    MySQL进阶part1
    java IO中的乱码问题
    解决在IDEA中无法使用Scanner输入的问题
    IDEA配置xml文件头报错:URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)
  • 原文地址:https://www.cnblogs.com/feshfans/p/9434290.html
Copyright © 2011-2022 走看看