`
RednaxelaFX
  • 浏览: 3052856 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

用Apache HttpClient 4.0时强制指定响应的字符编码

    博客分类:
  • Java
阅读更多
前两天一段调用HTTP服务的脚本出了问题,仔细一看,发现是提供的HTTP服务在响应头里写了:
HTTP/1.1 200 OK
Server: xxxxxxxxxx
Content-Type: text/html; charset=utf-8
Connection: close
Content-Length:2014

响应的头中声明了Content-Type,其中指定了charset=utf-8;但实际上响应中的文本却是GBK编码的。这使得原本我写的请求脚本出了问题。

依赖的Apache HttpClient如下:
pom.xml:
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpcomponents-client</artifactId>
  <version>4.0</version>
</dependency>
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpcomponents-core</artifactId>
  <version>4.0.1</version>
</dependency>


原本的脚本使用DefaultHttpClient去发起请求,并通过EntityUtils自己实现一个与BasicResponseHandler相似的ResponseHandler,类似这样的:
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

def httpClient = new DefaultHttpClient();
def makeResponseHandler(charset) {
  { response ->
      def statusLine = response.statusLine;
      if (statusLine.statusCode >= 300) {
        throw new HttpResponseException(statusLine.statusCode, statusLine.reasonPhrase);
      }
      
      def entity = response.entity;
      entity ? EntityUtils.toString(entity, charset) : null;
  } as ResponseHandler
}

def httpGet = new HttpGet(requestUrl);
def responseBody = httpClient.execute(httpGet, makeResponseHandler('GBK'));


原本要调用的那个HTTP服务返回的响应的头里面没有Content-Type,所以这样去使用EntityUtils.toString(entity, defaultCharset)就已经可以达到指定解析响应内容时使用的字符编码的目的了。

问题是那个HTTP服务现在带上了错误的Content-Type,而EntityUtils.toString(entity, defaultCharset)认为Content-Type中的charset比defaultCharset更优先,此时上面的脚本就达不到强制指定字符编码的目的了。

咋办呢?最直观的当然是自己把响应的内容的byte数组拿到手,然后自己想怎么处理就怎么处理:
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

def httpClient = new DefaultHttpClient();
def makeResponseHandler(charset) {
  { response ->
      def statusLine = response.statusLine;
      if (statusLine.statusCode >= 300) {
        throw new HttpResponseException(statusLine.statusCode, statusLine.reasonPhrase);
      }
      
      def entity = response.entity;
      def bytes = entity ? EntityUtils.toByteArray(entity) : null;
      bytes ? new String(bytes, charset) : null;
  } as ResponseHandler
}

def httpGet = new HttpGet(requestUrl);
def responseBody = httpClient.execute(httpGet, makeResponseHandler('GBK'));


不知道还有没有啥更好的办法呢?我对HttpClient还是太不熟悉了。

本来最好自然是提供HTTP服务的那边把响应头的信息修正,但这又要经过各种繁琐的流程,我在跟进的某工具却等不及了,只好hack一下 =_=
分享到:
评论
8 楼 sandssss 2011-01-18  
听说了这个坑爹的案例~~
7 楼 lwwin 2011-01-17  
RednaxelaFX 写道
lwwin 写道
真不好意思,呵呵,下次知道这个做什么用了^-^||
似乎比较类似make工具~

与其说像make,还不如说像…呃,这跟RubyGems也可以算像吧。至少普通的make是不帮忙抓依赖的,而POM会帮忙抓。


抓依赖美~ 以前经常因为依赖太多而又要手动配置心烦……
看到GROOVY语言的时候,水水真希望类C系列也有这么一套东西=x=!
兼容C++,又支持新特性……不知道有没有,以后有没有,C++0X还没看过……
6 楼 RednaxelaFX 2011-01-17  
lwwin 写道
真不好意思,呵呵,下次知道这个做什么用了^-^||
似乎比较类似make工具~

与其说像make,还不如说像…呃,这跟RubyGems也可以算像吧。至少普通的make是不帮忙抓依赖的,而POM会帮忙抓。
5 楼 lwwin 2011-01-17  
RednaxelaFX 写道
lwwin 写道
FX大似乎是主力=v=+ 开发工具什么的?

好像例子里面没有那个POM也可以跑的嘛,关于Maven似乎需要了解一下先~

这年头跟Java程序员说依赖的包是什么,用Maven的POM格式来说也算是流行的做法吧 = =


真不好意思,呵呵,下次知道这个做什么用了^-^||
似乎比较类似make工具~
4 楼 RednaxelaFX 2011-01-17  
lwwin 写道
FX大似乎是主力=v=+ 开发工具什么的?

好像例子里面没有那个POM也可以跑的嘛,关于Maven似乎需要了解一下先~

这年头跟Java程序员说依赖的包是什么,用Maven的POM格式来说也算是流行的做法吧 = =
3 楼 lwwin 2011-01-17  
FX大似乎是主力=v=+ 开发工具什么的?

好像例子里面没有那个POM也可以跑的嘛,关于Maven似乎需要了解一下先~
2 楼 RednaxelaFX 2011-01-16  
lwwin 写道
花了一整天,总算拼凑了个服务器然后跑出你那个问题- -

不过还有一些细节问问:
1) 所谓的“依赖的Apache HttpClient”是在客户端用的XML文件吗?
2) HTTP response 那段是在Groovy的程序里面打印显示的么?(不用抓包)
3) 不知道为啥bat在离开以后,里面设置的环境变量会被撤销……
@SETLOCAL ENABLEEXTENSIONS
@SETLOCAL ENABLEDELAYEDEXPANSION
@set "GROOVYPATH=."
@call path\add_classpath.bat E:\jLIBs\ApacheClient\httpcomponents-core-4.1\lib
@call path\add_classpath.bat E:\jLIBs\ApacheClient\httpcomponents-client-4.0.3\lib
::@echo current path : %GROOVYPATH%

在这里面打印echo是OK的,但是离开这个BAT以后似乎GROOVYPATH被重置了……

1) 那两段XML片段是Maven的POM配置文件的依赖声明
2) 是用curl -D来抓取的
3) 唔,BAT我一直不够熟悉,回答不了…
1 楼 lwwin 2011-01-16  
花了一整天,总算拼凑了个服务器然后跑出你那个问题- -

不过还有一些细节问问:
1) 所谓的“依赖的Apache HttpClient”是在客户端用的XML文件吗?
2) HTTP response 那段是在Groovy的程序里面打印显示的么?(不用抓包)
3) 不知道为啥bat在离开以后,里面设置的环境变量会被撤销……
@SETLOCAL ENABLEEXTENSIONS
@SETLOCAL ENABLEDELAYEDEXPANSION
@set "GROOVYPATH=."
@call path\add_classpath.bat E:\jLIBs\ApacheClient\httpcomponents-core-4.1\lib
@call path\add_classpath.bat E:\jLIBs\ApacheClient\httpcomponents-client-4.0.3\lib
::@echo current path : %GROOVYPATH%

在这里面打印echo是OK的,但是离开这个BAT以后似乎GROOVYPATH被重置了……

相关推荐

    httpclient4.0-jar

    在本篇文章中,我们将深入探讨HttpClient 4.0的核心特性,以及如何在实际开发中使用它。 首先,HttpClient 4.0的核心功能在于支持HTTP/1.1协议,包括GET、POST、PUT、DELETE等常见HTTP方法。它还支持HTTPS,确保...

    httpclient4.0

    HttpClient 4.0 引入了异步操作模型,允许在请求执行时解耦等待响应的过程。通过 `Future&lt;HttpResponse&gt;` 对象,开发者可以在其他线程中处理响应,提高程序的并发性能。 六、HttpClient 4.0 在实际项目中的应用 ...

    httpclient4.0 使用帮助、例子

    本篇文章将详细介绍HTTPClient 4.0的使用方法,包括其核心概念、基本操作和示例代码。 一、核心概念 1. HttpClient实例:HttpClient对象是执行HTTP请求的核心,负责建立连接、发送请求和接收响应。通过`...

    Httpclient4.0和3.0及jsoup等相关jar包

    1.含有官方HttpClient4.0的jar包 2.有之前HttpClient3.0的jar包,就是import importorg.apache.commons.*; 3.包含jsoup,解析HTML的jar包 4.包含jcookie.jar及jtidy-r938.jar的jar包.

    httpclient4.0源文件

    《HttpClient 4.0源码解析》 HttpClient是一款由Apache软件基金会开发的开源HTTP客户端库,主要用于处理HTTP请求和响应。HttpClient 4.0版本是其一个重要里程碑,它提供了更加强大、灵活和稳定的网络通信功能。在这...

    Apache httpclient源码4.5.12

    在学习HttpClient源码时,你可以深入理解HTTP协议的工作方式,了解如何使用Java进行网络编程,以及如何设计可扩展和高效的库。源码中的注释和设计模式也会帮助你提升Java编程技巧。 总的来说,Apache HttpClient ...

    httpclient-4.0.jar

    httpclient-4.0.jar, httpclient-4.0.jar, httpclient-4.0.jar

    HttpClient 4.0的post()方法4个关键“头信息”设置

    在探讨HttpClient 4.0的`post()`方法中四个关键“头信息”的设置之前,我们首先需要理解HttpClient是什么以及它在Java开发中的作用。 ### HttpClient简介 HttpClient是Apache的一个开源项目,它为Java应用程序提供...

    apache httpclient jar包

    Apache HttpClient是一款广泛使用的Java库,专门用于执行HTTP请求。它属于Apache HttpComponents项目的一部分,旨在提供一个高效、灵活且可扩展的HTTP客户端API。在Java应用程序中,如果你需要与Web服务器进行交互,...

    HttpClient 4.0学习

    HttpClient是Apache基金会开发的一个HTTP客户端库,主要用于处理HTTP请求和响应。HttpClient 4.0版本引入了许多改进和新特性,使其成为一个强大且灵活的HTTP通信工具。本篇将深入探讨HttpClient 4.0的主要功能、核心...

    使用httpClient组件解析html并解决字符编码

    使用HttpClient组件解析HTML并解决字符编码问题 在网络信息采集中,经常需要解析HTML页面以获取有用的信息。使用HttpClient组件可以轻松地实现这一任务。但是,在实际使用中,经常会遇到字符集编码乱码问题。本文将...

    原创: httpclient 4.0 使用 - 访问开心网的各种组件 例子

    《HttpClient 4.0 使用详解:访问开心网组件实例》 HttpClient 是 Apache 开源基金会提供的一个 HTTP 客户端库,被广泛应用于 Java 开发中,用于执行 HTTP 请求。HttpClient 4.0 版本引入了许多改进和新特性,使得...

    基于Java + HTTPClient 4.0,采用MySQL存储爬取数据,支持多进程并发执行的新浪微博爬虫

    【作品名称】:基于Java + HTTPClient 4.0,采用MySQL存储爬取数据,支持多进程并发执行的新浪微博爬虫 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训...

    HttpClient 4.0中文教程

    - **确保低级别资源释放**: 在使用HttpClient时,开发者需要注意释放资源,避免内存泄漏等问题。例如,关闭HttpResponse对象是非常重要的。 - **消耗实体内容**: 当收到响应时,必须显式地消耗实体内容,否则可能...

    Android升级后旧版本的httpclient4.0

    Android升级后旧版本的httpclient4.0 apache-mime4j-0.6 commons-codec-1.4 commons-logging-1.1.1 httpclient-4.0.1 httpcore-4.0.1 httpmime-4.0.1

    httpclient-4.0-beta1.jar

    httpclient-4.0-beta1.jar

    commons-httpclient依赖包

    包括了httpclient的所有包,commons-httpclient3.0.jar,httpclient4.0.jar,commons-logging1.1.1.jar,commons-codec-1.3.jar等

    apache HttpClient jar包

    这些文件对理解项目的许可条件、使用限制和最新更新至关重要,开发者在使用HttpClient时应仔细阅读。 总的来说,Apache HttpClient是Java开发者进行HTTP通信的强大工具,它的灵活性和可扩展性使得它在各种项目中都...

Global site tag (gtag.js) - Google Analytics