第六章 高级主题

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();
}

转载于:https://www.cnblogs.com/loveyakamoz/archive/2011/07/21/2113251.html

HttpClient 教程 (六)相关推荐

  1. [转]Android Studio系列教程六--Gradle多渠道打包

    转自:http://www.stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/ Android Studio系列教程六--Grad ...

  2. MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证

    视频地址:MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证 MongoDB数据库备份与恢复 一.备份 先介绍下命令语法: mongodump -h dbhost ...

  3. 以太坊构建DApps系列教程(六):使用定制代币进行投票

    在本系列关于使用以太坊构建DApps教程的第5部分中,我们讨论了如何为Story添加内容,查看如何添加参与者从DAO购买代币的功能以及在Story中添加提交内容.现在是编写DAO最终形式的时候了:投票 ...

  4. WPF教程六:布局之Grid面板(转)

    WPF教程六:布局之Grid面板 Grid:网格面板 Grid顾名思义就是"网格",以表格形式布局元素,对于整个面板上的元素进行布局,它的子控件被放在一个一个事先定义好的小格子里面 ...

  5. Laravel教程 六:表单 Forms

    Laravel教程 六:表单 Forms 此文章为原创文章,未经同意,禁止转载. Form laravel 5.2 之后请使用 laravelcollective/html 替换 illuminate ...

  6. VuePress搭建博客教程(六)、vuepress配置head和自定义样式

    VuePress搭建博客教程(六).vuepress配置head和自定义样式 小景哥哥博客 一.创建public文件夹 在.vuepress目录下创建public文件夹,在public文件夹下存入两个 ...

  7. 【STM32】标准库与HAL库对照学习教程六--位带操作

    [STM32]标准库与HAL库对照学习教程六--位带操作 一.前言 二.准备工作 三.位带介绍 1.位带操作 2.STM32位带及位带别名区域 四.位带区与位带别名区地址转换 五.GPIO的位带操作 ...

  8. 米思齐(Mixly)图形化系列教程(六)-for循环

    目录 For执行过程 省略 省略'循环变量赋值' 省略'循环条件' 省略"循环变量增量" FOR循环使用举例 遍历数组 顺序输出数据 指定程序重复执行次数 死循环 求和 教程导航 ...

  9. Symfony HttpClient教程

    Symfony HttpClient教程展示了如何使用HttpClient组件在 Symfony 中创建 HTTP 请求. 该组件提供使用 API​​ 的工具,并支持同步和异步操作. 有关更多信息,请 ...

  10. R语言七天入门教程六:文件相关操作

    R语言七天入门教程六:文件相关操作 一.文件的读写 R 语言作为统计学编程语言,常常需要处理大量数据,而这些数据通常会从文件中进行读取,因此文件读写在R语言中是非常重要的操作.在R语言中,用到最多的文 ...

最新文章

  1. ACwing 4. 多重背包问题 I(DP)
  2. ZZULIOJ 1102: 火车票退票费计算(函数专题)
  3. 创业一定要取个好名字,才容易实现人生逆袭
  4. HTTP协议学习总结三(常见http响应头)
  5. 工厂模式+抽象工厂模式
  6. JAVA NIO介绍及使用
  7. seo入门,seo入门基础知识
  8. 上海十大最美婚纱摄影外景地推荐
  9. SEO精准搜索流量的玩法
  10. “智多星”智能手机销售网
  11. 计算机三级选择难点及解析
  12. INSTALL_FAILED_NO_MATCHING_ABIS 的解决办法
  13. 订单功能模块设计与实现
  14. 实时时钟 (RTC)
  15. 文献阅读 ——— Pre-train, Prompt, and Predict: A Systematic Survey of Prompting Methods in NLP
  16. rails--图片的使用
  17. VS2013写智能电子钢琴
  18. softlayer 端口开放
  19. 计算机组装 仿真交互,《计算机硬件组装》仿真交互系统设计与实现.doc
  20. 刚当上leader,我让组员去开会,他非说有更重要的会

热门文章

  1. 【EMNLP 2020】篇章要素识别和篇章结构评分(上)
  2. pytorch 实现Gradient Flipping 各种坑
  3. PCA算法原理及实现
  4. 【论文笔记】NLP 预训练模型综述
  5. PyTorch学习—12.损失函数
  6. 大揭秘!RocketMQ如何管理消费进度
  7. 深度解析SDN——利益、战略、技术、实践(实战派专家力作,业内众多专家推荐)
  8. 产品管理有行业特殊性吗
  9. Android时代的赢创之路
  10. Tensorflow:可视化学习TensorBoard