HttpClient 教程 (三)

第三章 HTTP状态管理


始的HTTP是被设计为无状态的,面向请求/响应的协议,没有特殊规定有状态的,贯穿一些逻辑相关的请求/响应交换的会话。由于HTTP协议变得越来越普
及和受欢迎,越来越多的从前没有打算使用它的系统也开始为应用程序来使用它,比如作为电子商务应用程序的传输方式。因此,支持状态管理就变得非常必要了。


景公司,一度成为Web客户端和服务器软件开发者的领导方向,在它们基于专有规范的产品中实现了对HTTP状态管理的支持。之后,网景公司试图通过发布规
范草案来规范这种机制。它们的努力通过RFC标准跟踪促成了这些规范定义。然而,在很多应用程序中的状态管理仍然基于网景公司的草案而不兼容官方的规范。
很多主要的Web浏览器开发者觉得有必要保留那些极大促进标准片段应用程序的兼容性。

3.1 HTTP cookies

Cookie是HTTP代理和目标服务器可以交流保持会话的状态信息的令牌或短包。网景公司的工程师用它来指“魔法小甜饼”和粘住的名字。

HttpClient
使用Cookie接口来代表抽象的cookie令牌。在它的简单形式中HTTP的cookie几乎是名/值对。通常一个HTTP的cookie也包含一些
属性,比如版本号,合法的域名,指定cookie应用所在的源服务器URL子集的路径,cookie的最长有效时间。

SetCookie接口代表由源服务器发送给HTTP代理的响应中的头部信息Set-Cookie来维持一个对话状态。SetCookie2接口和指定的Set-Cookie2方法扩展了SetCookie。

SetCookie
接口和额外的如获取原始cookie属性的能力,就像它们由源服务器指定的客户端特定功能扩展了Cookie接口。这对生成Cookie头部很重要,因为
一些cookie规范需要。Cookie头部应该包含在Set-Cookie或Set-Cookie2头部中指定的特定属性。

3.1.1 Cookie版本

Cookie兼容网景公司的草案标准,但是版本0被认为是不符合官方规范的。符合标准的cookie的期望版本是1。HttpClient可以处理基于不同版本的cookie。

这里有一个重新创建网景公司草案cookie示例:

BasicClientCookie netscapeCookie = new BasicClientCookie("name", "value");

netscapeCookie.setVersion(0);

netscapeCookie.setDomain(".mycompany.com");

netscapeCookie.setPath("/");

这是一个重新创建标准cookie的示例。要注意符合标准的cookie必须保留由源服务器发送的所有属性:

BasicClientCookie stdCookie = new BasicClientCookie("name", "value");

stdCookie.setVersion(1);

stdCookie.setDomain(".mycompany.com");

stdCookie.setPath("/");

stdCookie.setSecure(true);

// 精确设置由服务器发送的属性

stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");

stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");

这是一个重新创建Set-Cookie2兼容cookie的实例。要注意符合标准的cookie必须保留由源服务器发送的所有属性:

BasicClientCookie2 stdCookie = new BasicClientCookie2("name", "value");

stdCookie.setVersion(1);

stdCookie.setDomain(".mycompany.com");

stdCookie.setPorts(new int[] {80,8080});

stdCookie.setPath("/");

stdCookie.setSecure(true);

// 精确设置由服务器发送的属性

stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");

stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");

stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");

3.2 Cookie规范

CookieSpec接口代表了cookie管理的规范。Cookie管理规范希望如下几点:

  • 解析的Set-Cookie规则还有可选的Set-Cookie2头部信息。
  • 验证解析cookie的规则。
  • 格式化给定主机的Cookie头部信息,原始端口和路径。

HttpClient附带了一些CookieSpec的实现:

  • 网景公司草案:这个规范符合由网景通讯发布的原始草案规范。应当避免,除非有绝对的必要去兼容遗留代码。
  • RFC 2109:官方HTTP状态管理规范并取代的老版本,被RFC 2965取代。
  • RFC 2965:官方HTTP状态管理规范。
  • 浏览器兼容性:这个实现努力去密切模仿(mis)通用Web浏览器应用程序的实现。比如微软的Internet Explorer和Mozilla的FireFox浏览器。
  • 最佳匹配:’Meta’(元)cookie规范采用了一些基于又HTTP响应发送的cookie格式的cookie策略。它基本上聚合了以上所有的实现到以一个类中。

强烈建议使用Best Match策略,让HttpClient在运行时基于执行上下文采用一些合适的兼容等级。

3.3 HTTP cookie和状态管理参数

这些是用于定制HTTP状态管理和独立的cookie规范行为的参数。

  • ‘http.protocol.cookie-
    datepatterns‘:定义了用于解析非标准的expires属性的合法日期格式。只是对兼容不符合规定的,仍然使用网景公司草案定义的
    expires而不使用标准的max-age属性服务器需要。这个参数期望得到一个java.util.Collection类型的值。集合元素必须是
    java.lang.String类型,来兼容java.text.SimpleDateFormat的语法。如果这个参数没有被设置,那么默认的选择就
    是CookieSpec实现规范的值。要注意这个参数的应用。
  • ‘http.protocol.single-
    cookie-header‘:定义了是否cookie应该强制到一个独立的Cookie请求头部信息中。否则,每个cookie就被当作分离的
    Cookie头部信息来格式化。这个参数期望得到一个java.lang.Boolean类型的值。如果这个参数没有被设置,那么默认的选择就是
    CookieSpec实现规范的值。要注意这个参数仅仅严格应用于cookie规范(RFC 2109和RFC
    2965)。浏览器兼容性和网景公司草案策略将会放置所有的cookie到一个请求头部信息中。
  • ‘http.protocol.cookie-policy‘:定义了用于HTTP状态管理的cookie规范的名字。这个参数期望得到一个java.lang.String类型的值。如果这个参数没有被设置,那么合法的日期格式就是CookieSpec实现规范的值。

3.4 Cookie规范注册表

HttpClient使用CookieSpecRegistry类维护一个可用的cookie规范注册表。下面的规范对于每个默认都是注册过的:

  • 兼容性:浏览器兼容性(宽松策略)。
  • 网景:网景公司草案。
  • rfc2109:RFC 2109(过时的严格策略)。
  • rfc2965:RFC 2965(严格策略的标准符合)。
  • best-match:最佳匹配meta(元)策略。

3.5 选择cookie策略

Cookie策略可以在HTTP客户端被设置,如果需要,在HTTP请求级重写。

HttpClient httpclient = new DefaultHttpClient();

// 对每个默认的强制严格cookie策略

httpclient.getParams().setParameter(

ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);

HttpGet httpget = new HttpGet("http://www.broken-server.com/");

// 对这个请求覆盖默认策略

httpget.getParams().setParameter(

ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);

3.6 定制cookie策略


了实现定制cookie策略,我们应该创建CookieSpec接口的定制实现类,创建一个CookieSpecFactory实现来创建和初始化定制实
现的实例并和HttpClient注册这个工厂。一旦定制实现被注册了,它可以和标准的cookie实现有相同的活性。

CookieSpecFactory csf = new CookieSpecFactory() {

public CookieSpec newInstance(HttpParams params) {

return new BrowserCompatSpec() {

@Override

public void validate(Cookie cookie, CookieOrigin origin)

throws MalformedCookieException {

// 这相当简单

}

};

}

};

DefaultHttpClient httpclient = new DefaultHttpClient();

httpclient.getCookieSpecs().register("easy", csf);

httpclient.getParams().setParameter(

ClientPNames.COOKIE_POLICY, "easy");

3.7 Cookie持久化

HttpClient
可以和任意物理表示的实现了CookieStore接口的持久化cookie存储一起使用。默认的CookieStore实现称为
BasicClientCookie,这是凭借java.util.ArrayList的一个简单实现。在BasicClientCookie对象中存储
的cookie当容器对象被垃圾回收机制回收时会丢失。如果需要,用户可以提供更复杂的实现。

DefaultHttpClient httpclient = new DefaultHttpClient();

// 创建一个本地的cookie store实例

CookieStore cookieStore = new MyCookieStore();

// 如果需要填充cookie

BasicClientCookie cookie = new BasicClientCookie("name", "value");

cookie.setVersion(0);

cookie.setDomain(".mycompany.com");

cookie.setPath("/");

cookieStore.addCookie(cookie);

// 设置存储

httpclient.setCookieStore(cookieStore);

3.8 HTTP状态管理和执行上下文

在HTTP请求执行的过程中,HttpClient添加了下列和状态管理相关的对象到执行上下文中:

  • ‘http.cookiespec-registry‘:CookieSpecRegistry实例代表了实际的cookie规范注册表。这个属性的值设置在本地内容中,优先于默认的。
  • ‘http.cookie-spec‘:CookieSpec实例代表真实的cookie规范。
  • ‘http.cookie-origin‘:CookieOrigin实例代表了真实的源服务器的详细信息。
  • ‘http.cookie-store‘:CookieStore实例代表了真实的cookie存储。设置在本地内容中的这个属性的值优先于默认的。

本地的HttpContext对象可以被用来定制HTTP状态管理内容,先于请求执行或在请求执行之后检查它的状态:

HttpClient httpclient = new DefaultHttpClient();

HttpContext localContext = new BasicHttpContext();

HttpGet httpget = new HttpGet("http://localhost:8080/");

HttpResponse response = httpclient.execute(httpget, localContext);

CookieOrigin cookieOrigin = (CookieOrigin) localContext.getAttribute(

ClientContext.COOKIE_ORIGIN);

System.out.println("Cookie origin: " + cookieOrigin);

CookieSpec cookieSpec = (CookieSpec) localContext.getAttribute(

ClientContext.COOKIE_SPEC);

System.out.println("Cookie spec used: " + cookieSpec);

3.9 每个用户/线程的状态管理

我们可以使用独立的本地执行上下文来实现对每个用户(或每个线程)状态的管理。定义在本地内容中的cookie规范注册表和cookie存储将会优先于设置在HTTP客户端级别中默认的那些。

HttpClient httpclient = new DefaultHttpClient();

// 创建cookie store的本地实例

CookieStore cookieStore = new BasicCookieStore();

// 创建本地的HTTP内容

HttpContext localContext = new BasicHttpContext();

// 绑定定制的cookie store到本地内容中

localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

HttpGet httpget = new HttpGet("http://www.google.com/");

// 作为参数传递本地内容

HttpResponse response = httpclient.execute(httpget, localContext)

时间: 2024-11-29 08:26:02

HttpClient 教程 (三)的相关文章

HttpClient教程

HttpClient教程 2017-03-29 官方文档:http://hc.apache.org/httpcomponents-client-ga/ HttpClient Tutorial翻译文档: 第一章 基础 第二章 连接管理 第三章 HTTP状态管理 第四章 HTTP认证 第五章 HTTP客户端服务 第六章 高级主题 封装HttpClient 轻松把玩HttpClient之封装HttpClient工具类

HttpClient 教程 (一)

前言 超文本传输协议(HTTP)也许是当今互联网上使用的最重要的协议了.Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web浏览器范畴,同时,也增加了需要HTTP协议支持的应用程序的数量. 尽管java.net包提供了基本通过HTTP访问资源的功能,但它没有提供全面的灵活性和其它很多应用程序需要的功能.HttpClient就是寻求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议. 为扩展而设计

微信开放平台 公众号第三方平台开发 教程三 一键登录授权给第三方平台

原文:微信开放平台 公众号第三方平台开发 教程三 一键登录授权给第三方平台 教程导航: 微信开放平台 公众号第三方平台开发 教程一 平台介绍 微信开放平台 公众号第三方平台开发 教程二 创建公众号第三方平台 微信开放平台 公众号第三方平台开发 教程三 一键登录授权给第三方平台 微信开放平台 公众号第三方平台开发 教程四 代公众号调用接口的SDK和demo 公众号第三方平台的开放,是为了让公众号运营者,在面向垂直行业需求时,可以一键登录授权给第三方的公众号运营平台,通过第三方开发者提供的公众号第三

struts2 官方系列教程三:使用struts2 标签 tag

避免被爬,先贴上本帖地址:struts2 官方系列教程一:使用struts2 标签 tag http://www.cnblogs.com/linghaoxinpian/p/6901316.html 本教材假定你已完成了HelloWorld项目,你可以在 struts2 官方系列教程三:使用struts2 标签 tag 下载本章节的代码 在上一节教程中,我们在index.jsp中使用 url tag 创建了一个超链接hello.action 这节我们将探索struts2中其它tags Web应用程

Junit 4 Tutorials(Junit 4 教程) 三、Junit4 断言方法

Junit 4 断言方法允许检查测试方法的期望结果值和真实返回值.Junit的org.junit.Assert类提供了各种断言方法来写junit测试.这些方法被用来检查方法的真实结果值和期望值.下列一些有用的断言方法列表: Junit 4 Assert Methods Method Description assertNull(java.lang.Object object) 检查对象是否为空 assertNotNull(java.lang.Object object) 检查对象是否不为空 as

Swift中文教程(三)--流程控制

原文:Swift中文教程(三)--流程控制 Swift用if和switch编写条件控制语句,用for-in,for,while和do-while编写循环.条件控制语句和循环语句中,小括号是可选的,但花括号包住这个循环体是必须的: 1 let individualScores = [75, 43, 103, 87, 12] 2 var teamScore = 0 3 for score in individualScores { 4 if score > 50 { 5 teamScore += 3

Struts2.x教程(三) Struts2拦截器

一.Struts2拦截器介绍 Struts2拦截器是使用AOP实现的,主要是针对action对象进行拦截,可以在访问action的某个方法.字段之前或之后实施拦截. 可以为action配置多个拦截器,Struts2会将这一组拦截器按照一定顺序组织成一个拦截器栈.action可以直接引用某个拦截器栈来实现配置多个拦截器的目的. 对于继承struts_default的package中的action,都会默认引用name=defaultStack的拦截器栈(在struts_default中定义了Str

jQuery 入门教程(三): Selectors

jQuery Selector 是jQuery库中非常重要的一个组成部分. jQuery Selector 用来选择某个HTML元素,其基本语句和CSS的选择器(Selector)是一样的,所有jQuery selector 都是以$()开始. 选择HTML标记 选择某个HTML元素的方法是直接使用该元素的标记名称,比如选择所有<p>元素 $("p") 下面的例子当用户点击一个按钮时,隐藏所有的<p>元素 $(document).ready(function()

BootStrap入门教程 (三)

上讲回顾:Bootstrap的基础CSS(Base CSS)提供了优雅,一致的多种基础Html页面要素,包括排版,表格,表单,按钮等,能够满足前端工程师的基本要素需求. Bootstrap作为完整的前端工具集,内建了大量的强大优雅可重用的组件,包括按钮(Button),导航(Navigation),标签(Labels),徽章(Badges),排版(Typography),缩略图( thumbnails),提醒(Alert),进度条(progress bar),杂项(Miscellaneous).