HttpClient 教程 (六)
第六章 高级主题
6.1 自定义客户端连接
在特定条件下,也许需要来定制HTTP报文通过线路传递,越过了可能使用的HTTP参数来处理非标准不兼容行为的方式。比如,对于Web爬虫,它可能需要强制HttpClient接受格式错误的响应头部信息,来抢救报文的内容。
通常插入一个自定义的报文解析器的过程或定制连接实现需要几个步骤:
提供一个自定义LineParser/LineFormatter接口实现。如果需要,实现报文解析/格式化逻辑。
class MyLineParser extends BasicLineParser {
@Override
public Header parseHeader(
final CharArrayBuffer buffer) throws ParseException {
try {
return super.parseHeader(buffer);
} catch (ParseException ex) {
// 压制ParseException异常
return new BasicHeader("invalid", buffer.toString());
}
}
}
提过一个自定义的OperatedClientConnection实现。替换需要自定义的默认请求/响应解析器,请求/响应格式化器。如果需要,实现不同的报文写入/读取代码。
class MyClientConnection extends DefaultClientConnection {
@Override
protected HttpMessageParser createResponseParser(
final SessionInputBuffer buffer,
final HttpResponseFactory responseFactory,
final HttpParams params) {
return new DefaultResponseParser(buffer,
new MyLineParser(),responseFactory,params);
}
}
为了创建新类的连接,提供一个自定义的ClientConnectionOperator接口实现。如果需要,实现不同的套接字初始化代码。
class MyClientConnectionOperator extends
DefaultClientConnectionOperator {
public MyClientConnectionOperator(
final SchemeRegistry sr) {
super(sr);
}
@Override
public OperatedClientConnection createConnection() {
return new MyClientConnection();
}
}
为了创建新类的连接操作,提供自定义的ClientConnectionManager接口实现。
class MyClientConnManager extends SingleClientConnManager {
public MyClientConnManager(
final HttpParams params,
final SchemeRegistry sr) {
super(params, sr);
}
@Override
protected ClientConnectionOperator createConnectionOperator(
final SchemeRegistry sr) {
return new MyClientConnectionOperator(sr);
}
}
6.2 有状态的HTTP连接
HTTP规范假设session状态信息通常是以HTTP cookie格式嵌入在HTTP报文中的,因此HTTP连接通常是无状态的,这个假设在现实生活中通常是不对的。也有一些情况,当HTTP连接使用特定的用户标识或特定的安全上下文来创建时,因此不能和其它用户共享,只能由该用户重用。这样的有状态的HTTP连接的示例就是NTLM认证连接和使用客户端证书认证的SSL连接。
6.2.1 用户令牌处理器
HttpClient依赖UserTokenHandler接口来决定给定的执行上下文是否是用户指定的。如果这个上下文是用户指定的或者如果上下文没有包含任何资源或关于当前用户指定详情而是null,令牌对象由这个处理器返回,期望唯一地标识当前的用户。用户令牌将被用来保证用户指定资源不会和其它用户来共享或重用。
如果它可以从给定的执行上下文中来获得,UserTokenHandler接口的默认实现是使用主类的一个实例来代表HTTP连接的状态对象。UserTokenHandler将会使用基于如NTLM或开启的客户端认证SSL会话认证模式的用户的主连接。如果二者都不可用,那么就不会返回令牌。
如果默认的不能满足它们的需要,用户可以提供一个自定义的实现:
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setUserTokenHandler(new UserTokenHandler() {
public Object getUserToken(HttpContext context) {
return context.getAttribute("my-token");
}
});
6.2.2 用户令牌和执行上下文
在HTTP请求执行的过程中,HttpClient添加了下列和用户标识相关的对象到执行上下文中:
'http.user-token':对象实例代表真实的用户标识,通常期望Principle接口的实例。
我们可以在请求被执行后,通过检查本地HTTP上下文的内容,发现是否用于执行请求的连接是有状态的。
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("http://localhost:8080/");
HttpResponse response = httpclient.execute(httpget, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
Object userToken = localContext.getAttribute(ClientContext.USER_TOKEN);
System.out.println(userToken);
6.2.2.1 持久化有状态的连接
请注意带有状态对象的持久化连接仅当请求被执行时,相同状态对象被绑定到执行上下文时可以被重用。所以,保证相同上下文重用于执行随后的相同用户,或用户令牌绑定到之前请求执行上下文的HTTP请求是很重要的。
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext1 = new BasicHttpContext();
HttpGet httpget1 = new HttpGet("http://localhost:8080/");
HttpResponse response1 = httpclient.execute(httpget1, localContext1);
HttpEntity entity1 = response1.getEntity();
if (entity1 != null) {
entity1.consumeContent();
}
Principal principal = (Principal) localContext1.getAttribute(
ClientContext.USER_TOKEN);
HttpContext localContext2 = new BasicHttpContext();
localContext2.setAttribute(ClientContext.USER_TOKEN, principal);
HttpGet httpget2 = new HttpGet("http://localhost:8080/");
HttpResponse response2 = httpclient.execute(httpget2, localContext2);
HttpEntity entity2 = response2.getEntity();
if (entity2 != null) {
entity2.consumeContent();
}
第六章 高级主题
6.1 自定义客户端连接
在特定条件下,也许需要来定制HTTP报文通过线路传递,越过了可能使用的HTTP参数来处理非标准不兼容行为的方式。比如,对于Web爬虫,它可能需要强制HttpClient接受格式错误的响应头部信息,来抢救报文的内容。
通常插入一个自定义的报文解析器的过程或定制连接实现需要几个步骤:
提供一个自定义LineParser/LineFormatter接口实现。如果需要,实现报文解析/格式化逻辑。
class MyLineParser extends BasicLineParser {
@Override
public Header parseHeader(
final CharArrayBuffer buffer) throws ParseException {
try {
return super.parseHeader(buffer);
} catch (ParseException ex) {
// 压制ParseException异常
return new BasicHeader("invalid", buffer.toString());
}
}
}
提过一个自定义的OperatedClientConnection实现。替换需要自定义的默认请求/响应解析器,请求/响应格式化器。如果需要,实现不同的报文写入/读取代码。
class MyClientConnection extends DefaultClientConnection {
@Override
protected HttpMessageParser createResponseParser(
final SessionInputBuffer buffer,
final HttpResponseFactory responseFactory,
final HttpParams params) {
return new DefaultResponseParser(buffer,
new MyLineParser(),responseFactory,params);
}
}
为了创建新类的连接,提供一个自定义的ClientConnectionOperator接口实现。如果需要,实现不同的套接字初始化代码。
class MyClientConnectionOperator extends
DefaultClientConnectionOperator {
public MyClientConnectionOperator(
final SchemeRegistry sr) {
super(sr);
}
@Override
public OperatedClientConnection createConnection() {
return new MyClientConnection();
}
}
为了创建新类的连接操作,提供自定义的ClientConnectionManager接口实现。
class MyClientConnManager extends SingleClientConnManager {
public MyClientConnManager(
final HttpParams params,
final SchemeRegistry sr) {
super(params, sr);
}
@Override
protected ClientConnectionOperator createConnectionOperator(
final SchemeRegistry sr) {
return new MyClientConnectionOperator(sr);
}
}
6.2 有状态的HTTP连接
HTTP规范假设session状态信息通常是以HTTP cookie格式嵌入在HTTP报文中的,因此HTTP连接通常是无状态的,这个假设在现实生活中通常是不对的。也有一些情况,当HTTP连接使用特定的用户标识或特定的安全上下文来创建时,因此不能和其它用户共享,只能由该用户重用。这样的有状态的HTTP连接的示例就是NTLM认证连接和使用客户端证书认证的SSL连接。
6.2.1 用户令牌处理器
HttpClient依赖UserTokenHandler接口来决定给定的执行上下文是否是用户指定的。如果这个上下文是用户指定的或者如果上下文没有包含任何资源或关于当前用户指定详情而是null,令牌对象由这个处理器返回,期望唯一地标识当前的用户。用户令牌将被用来保证用户指定资源不会和其它用户来共享或重用。
如果它可以从给定的执行上下文中来获得,UserTokenHandler接口的默认实现是使用主类的一个实例来代表HTTP连接的状态对象。UserTokenHandler将会使用基于如NTLM或开启的客户端认证SSL会话认证模式的用户的主连接。如果二者都不可用,那么就不会返回令牌。
如果默认的不能满足它们的需要,用户可以提供一个自定义的实现:
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setUserTokenHandler(new UserTokenHandler() {
public Object getUserToken(HttpContext context) {
return context.getAttribute("my-token");
}
});
6.2.2 用户令牌和执行上下文
在HTTP请求执行的过程中,HttpClient添加了下列和用户标识相关的对象到执行上下文中:
'http.user-token':对象实例代表真实的用户标识,通常期望Principle接口的实例。
我们可以在请求被执行后,通过检查本地HTTP上下文的内容,发现是否用于执行请求的连接是有状态的。
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("http://localhost:8080/");
HttpResponse response = httpclient.execute(httpget, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
Object userToken = localContext.getAttribute(ClientContext.USER_TOKEN);
System.out.println(userToken);
6.2.2.1 持久化有状态的连接
请注意带有状态对象的持久化连接仅当请求被执行时,相同状态对象被绑定到执行上下文时可以被重用。所以,保证相同上下文重用于执行随后的相同用户,或用户令牌绑定到之前请求执行上下文的HTTP请求是很重要的。
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext1 = new BasicHttpContext();
HttpGet httpget1 = new HttpGet("http://localhost:8080/");
HttpResponse response1 = httpclient.execute(httpget1, localContext1);
HttpEntity entity1 = response1.getEntity();
if (entity1 != null) {
entity1.consumeContent();
}
Principal principal = (Principal) localContext1.getAttribute(
ClientContext.USER_TOKEN);
HttpContext localContext2 = new BasicHttpContext();
localContext2.setAttribute(ClientContext.USER_TOKEN, principal);
HttpGet httpget2 = new HttpGet("http://localhost:8080/");
HttpResponse response2 = httpclient.execute(httpget2, localContext2);
HttpEntity entity2 = response2.getEntity();
if (entity2 != null) {
entity2.consumeContent();
}
发表评论
-
代码混淆
2013-05-18 14:31 842代码混淆: http://wenku.baidu.com/ ... -
apk签名方法
2012-12-17 14:36 864签名证书,方式相同包名的不同apk互相覆盖安装。 1. ... -
Ubuntu安装Android开发环境
2012-11-17 00:38 17101、JDK安装 在下载JDK,官网地址为:http://ww ... -
Android之完美退出所有activity方法
2012-07-10 18:52 1067/*还有一种比较流行的Android经典完美退出方法,使用单例 ... -
android 焦点问题
2012-06-04 12:31 4050参考地址:http://blog.csdn.net/zhang ... -
Android报表工具
2012-05-11 16:11 1403Android报表工具下载地址:http://code.goo ... -
Android 推送
2012-04-01 13:44 1409关于服务器端向Android客户端的推送,主要有三种方 ... -
HttpClient 教程 (五)
2012-03-21 13:26 900第五章 HTTP客户端服务 5.1 HttpClient门 ... -
HttpClient 教程 (四)
2012-03-21 13:26 1059第四章 HTTP认证 HttpClient ... -
HttpClient 教程 (三)
2012-03-21 13:26 1263HttpClient 教程 (三) 第三章 HTTP状态管理 ... -
HttpClient 教程 (二)
2012-03-20 15:48 1061HttpClient 教程 (二) 第二章 连接管理 Htt ... -
HttpClient 教程 (一)
2012-03-20 15:47 991HttpClient 教程 (一) 前言 ... -
HTTP客户端服务
2012-03-20 15:39 13555.1 HttpClient门面 HttpClient接口代 ... -
Android 网络开发详解
2012-03-19 16:41 1220// 创建一个 HttpClient 实例 // 注意 H ... -
关于虚拟机AVD:Android Virtual Devices
2012-03-15 15:51 9821.拷贝虚拟SD卡文件至本地: DDMS视图->File ... -
向SD卡写文件
2012-03-15 15:47 993AndroidManifest.xml: SD卡创建与删除文 ... -
Android 近百个项目的源代码,覆盖Android开发的每个领域
2012-03-08 12:18 872Android PDF 阅读器 http://sourcefo ... -
关于谷歌地图的问题:requires unavailable shared library com.google.android.maps
2012-03-08 09:28 6492关于谷歌地图和百度地图的抉择: 补充:http://news ... -
Android Google Maps API key 申请
2012-03-07 15:17 20091.找debug.keystore文件路径: Eclipse- ... -
Android的断点设置
2012-03-07 14:46 3908Note: 在onCreate方法中加入Debug.waitF ...
相关推荐
### Httpclient教程 #### 一、简介 在深入讲解如何使用`Httpclient`之前,我们首先需要了解`Httpclient`是什么以及它为何如此重要。`Httpclient`是Apache的一个开源项目,它提供了一套用于HTTP协议操作的客户端API...
### HttpClient 4.0中文教程知识点总结 #### 一、HttpClient概述 **1.1 执行请求** - **HTTP请求**: HTTP请求包含了方法名称(GET、POST等)、URL以及必要的请求头信息。HttpClient允许开发者创建并发送这些请求...
本教程将详细介绍HttpClient 4.3的主要特性和使用方法。 一、HttpClient简介 HttpClient是一个Java库,它允许开发人员执行HTTP和HTTPS请求,并处理响应。它支持各种HTTP方法(如GET、POST、PUT、DELETE等),提供了...
### HttpClient 教程知识点解析 #### 一、HttpClient与HttpCore概述 **HttpClient**是Apache组织下的一款开源库,主要用于Java应用中发送HTTP请求和处理响应。它提供了一种高效、灵活的方式,来构建和执行HTTP请求...
#### 五、使用教程 ##### 5.1 编程步骤 使用HttpClient4组件进行编程的基本步骤包括: 1. **创建HttpClient实例**:通常使用`DefaultHttpClient`实现类。 2. **创建HTTP请求方法**:例如`HttpGet`、`HttpPost`等...
### HttpClient教程概览 #### 一、基础知识 **1.1 执行请求** - **HTTP 请求**:HTTP 请求包括请求行、请求头和可能的消息体。请求行包含方法(如GET、POST)、请求URI和HTTP版本。请求头包含了客户端希望服务器...
下面是 Angular HttpClient 的简单入门教程。 一、准备工作 在使用 Angular HttpClient 之前,需要在应用程序的模块中导入 HttpClientModule。例如,在 `app.module.ts` 文件中添加以下代码: ```typescript ...
HttpClient是Apache基金会开发的一个HTTP客户端库,用于在Java应用程序中执行HTTP请求。...参考文档:《HttpClient中文教程》PDF,该文档详尽地介绍了HttpClient的使用方法和高级特性,是学习HttpClient的宝贵资源。
2. **HttpClient**:在Java中,可以使用Apache HttpClient库来构造和发送SOAP请求。 七、SOAP与RESTful对比 RESTful API基于HTTP协议,使用URI(Uniform Resource Identifier)标识资源,通过HTTP方法(GET、POST、...
**六、表单处理** Angular2提供了两种表单模式:模板驱动表单(Template-driven forms)和响应式表单(Reactive forms)。它们分别对应不同的使用场景,提供了验证、模型驱动等高级特性。 **七、HTTP服务** Angular...
**六、性能优化** 1. **变更检测**:AngularJS 2的变更检测策略比1.x更高效,如OnPush策略,仅在输入属性变化时才更新组件。 2. **懒加载**:通过路由懒加载,可以按需加载模块,减少初始加载时间,提升用户体验。...
六、FTP和SMTP C#还提供了FTP(文件传输协议)和SMTP(简单邮件传输协议)的支持。WebClient类可以进行FTP上传和下载,SmtpClient类则用于发送电子邮件。 七、异常处理与安全 网络编程中,异常处理至关重要。例如,...
《Android入门到精通教程》是一套全面且深入的Android开发学习资源,包含了从基础到高级的各个层次的知识点。这份PPT课件共分为十五个章节,旨在帮助初学者逐步建立起对Android开发的全面理解,并进一步提升专业技能...
4. **表单与数据校验**(7 第六节:表单与数据校验.mp4):Angular2提供了两种表单模式:模板驱动和响应式表单,用于处理用户输入和验证数据。这部分内容可能详细讲解了这两种表单的创建、数据绑定、表单控件状态...
#### 六、服务与广播接收器 1. **服务(Service)**:后台运行的任务,不提供用户界面,可用于执行长时间的操作如音乐播放。 2. **广播接收器(BroadcastReceiver)**:监听和响应来自系统或其他应用的广播消息。 3...
Java标准库提供了`java.net.HttpURLConnection`来发送HTTP请求,但实际开发中,我们常常会使用第三方库,如Apache HttpClient或OkHttp,它们提供了更强大的功能和易用性。 七、HTTPS安全通信 在处理敏感数据时,...
### C# 初级学习教程知识点详解 #### 一、C# 语言简介 - **定义**:C#(发音为“C Sharp”)是一种面向对象的编程语言,由微软公司开发并首次发布于2000年。它是.NET Framework 的主要编程语言之一。 - **特点**: ...