HttpClient4.3教程 第三章 Http状态管理

HttpClient4.3教程 第三章 Http状态管理

Posted on 2013 年 10 月 13 日

最初,Http被设计成一个无状态的,面向请求/响应的协议,所以它不能在逻辑相关的http请求/响应中保持状态会话。由于越来越多的系统使用http协议,其中包括http从来没有想支持的系统,比如电子商务系统。因此,http支持状态管理就很必要了。

当时的web客户端和服务器软件领先者,网景(netscape)公司,最先在他们的产品中支持http状态管理,并且制定了一些专有规范。后来,网景通过发规范草案,规范了这一机制。这些努力促成 RFC standard track制定了标准的规范。但是,现在多数的应用的状态管理机制都在使用网景公司的规范,而网景的规范和官方规定是不兼容的。因此所有的浏览器开发这都被迫兼容这两种协议,从而导致协议的不统一。

3.1.Http cookies

所谓的Http cookie就是一个token或者很短的报文信息,http代理和服务器可以通过cookie来维持会话状态。网景的工程师把它们称作“magic cookie”。

HttpClient使用Cookie接口来代表cookie。简单说来,cookie就是一个键值对。一般,cookie也会包含版本号、域名、路径和cookie有效期。

SetCookie接口可以代表服务器发给http代理的一个set-cookie响应头,在浏览器中,这个set-cookie响应头可以写入cookie,以便保持会话状态。SetCookie2接口对SetCookie接口进行了拓展,添加了Set-Cookie2方法。

ClientCookie接口继承了Cookie接口,并进行了功能拓展,比如它可以取出服务器发送过来的原始cookie的值。生成头消息是很重要的,因为只有当cookie被指定为Set-Cookie或者Set-Cookie2时,它才需要包括一些特定的属性。

3.1.1COOKIES版本

兼容网景的规范,但是不兼容官方规范的cookie,是版本0. 兼容官方规范的版本,将会是版本1。版本1中的Cookie可能和版本0工作机制有差异。

下面的代码,创建了网景版本的Cookie:

    BasicClientCookie netscapeCookie = new BasicClientCookie("name", "value");
    netscapeCookie.setVersion(0);
    netscapeCookie.setDomain(".yeetrack.com");
    netscapeCookie.setPath("/");

下面的代码,创建标准版本的Cookie。注意,标准版本的Cookie必须保留服务器发送过来的Cookie所有属性。

    BasicClientCookie stdCookie = new BasicClientCookie("name", "value");
    stdCookie.setVersion(1);
    stdCookie.setDomain(".yeetrack.com");
    stdCookie.setPath("/");
    stdCookie.setSecure(true);
    // Set attributes EXACTLY as sent by the server
    stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
    stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".yeetrack.com");

下面的代码,创建了Set-Cookie2兼容cookie。

    BasicClientCookie2 stdCookie = new BasicClientCookie2("name", "value");
    stdCookie.setVersion(1);
    stdCookie.setDomain(".yeetrack.com");
    stdCookie.setPorts(new int[] {80,8080});
    stdCookie.setPath("/");
    stdCookie.setSecure(true);
    // Set attributes EXACTLY as sent by the server
    stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
    stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".yeetrack.com");
    stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");

3.2. Cookie规范

CookieSpec接口代表了Cookie管理规范。Cookie管理规范规定了:

  • 解析Set-CookieSet-Cookie2(可选)头消息的规则
  • 验证Cookie的规则
  • 将指定的主机名、端口和路径格式化成Cookie头消息

HttpClient有下面几种CookieSpec规范:

  • Netscape draft: 这种符合网景公司指定的规范。但是尽量不要使用,除非一定要保证兼容很旧的代码。
  • Standard: RFC 2965 HTTP状态管理规范
  • Browser compatibility: 这种方式,尽量模仿常用的浏览器,如IE和firefox
  • Best match: ‘Meta’ cookie specification that picks up a cookie policy based on the format of cookies sent with the HTTP response.它基本上将上面的几种规范积聚到一个类中。
    ++ Ignore cookies: 忽略所有Cookie
    强烈推荐使用Best Match匹配规则,让HttpClient根据运行时环境自己选择合适的规范。

3.3.选择Cookie策略

我们可以在创建Http client的时候指定Cookie测试,如果需要,也可以在执行http请求的时候,进行覆盖指定。

    RequestConfig globalConfig = RequestConfig.custom()
            .setCookieSpec(CookieSpecs.BEST_MATCH)
            .build();
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultRequestConfig(globalConfig)
            .build();
    RequestConfig localConfig = RequestConfig.copy(globalConfig)
            .setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY)
            .build();
    HttpGet httpGet = new HttpGet("http://www.yeetrack.com");
    httpGet.setConfig(localConfig);

3.4.自定义Cookie策略

如果我们要自定义Cookie测试,就要自己实现CookieSpec接口,然后创建一个CookieSpecProvider接口来新建、初始化自定义CookieSpec接口,最后把CookieSpecProvider注册到HttpClient中。一旦我们注册了自定义策略,就可以像其他标准策略一样使用了。

    CookieSpecProvider easySpecProvider = new CookieSpecProvider() {

        public CookieSpec create(HttpContext context) {

            return new BrowserCompatSpec() {
                @Override
                public void validate(Cookie cookie, CookieOrigin origin)
                        throws MalformedCookieException {
                    // Oh, I am easy
                }
            };
        }

    };
    Registry<CookieSpecProvider> r = RegistryBuilder.<CookieSpecProvider>create()
            .register(CookieSpecs.BEST_MATCH,
                new BestMatchSpecFactory())
            .register(CookieSpecs.BROWSER_COMPATIBILITY,
                new BrowserCompatSpecFactory())
            .register("easy", easySpecProvider)
            .build();

    RequestConfig requestConfig = RequestConfig.custom()
            .setCookieSpec("easy")
            .build();

    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCookieSpecRegistry(r)
            .setDefaultRequestConfig(requestConfig)
            .build();

3.5.Cookie持久化

HttpClient可以使用任何存储方式的cookie store,只要这个cookie store实现了CookieStore接口。默认的CookieStore通过java.util.ArrayList简单实现了BasicCookieStore。存在在BasicCookieStore中的Cookie,当载体对象被当做垃圾回收掉后,就会丢失。如果必要,用户可以自己实现更为复杂的方式。

    // 创建CookieStore实例
    CookieStore cookieStore = new BasicCookieStore();
    // 新建一个Cookie
    BasicClientCookie cookie = new BasicClientCookie("name", "value");
    cookie.setVersion(0);
    cookie.setDomain(".mycompany.com");
    cookie.setPath("/");
    cookieStore.addCoo
    //将CookieStore设置到httpClient中
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCookieStore(cookieStore)
            .build();

3.6.HTTP状态管理和执行上下文

在Http请求执行过程中,HttpClient会自动向执行上下文中添加下面的状态管理对象:

  • Lookup对象 代表实际的cookie规范registry。在当前上下文中的这个值优先于默认值。
  • CookieSpec对象 代表实际的Cookie规范。
  • CookieOrigin对象 代表实际的origin server的详细信息。
  • CookieStore对象 表示Cookie store。这个属性集中的值会取代默认值。

本地的HttpContext对象可以用来在Http请求执行前,自定义Http状态管理上下文;或者测试http请求执行完毕后上下文的状态。我们也可以在不同的线程中使用不同的执行上下文。我们在http请求层指定的cookie规范集和cookie store会覆盖在http Client层级的默认值。

    CloseableHttpClient httpclient = <...>

    Lookup<CookieSpecProvider> cookieSpecReg = <...>
    CookieStore cookieStore = <...>

    HttpClientContext context = HttpClientContext.create();
    context.setCookieSpecRegistry(cookieSpecReg);
    context.setCookieStore(cookieStore);
    HttpGet httpget = new HttpGet("http://somehost/");
    CloseableHttpResponse response1 = httpclient.execute(httpget, context);
    <...>
    // Cookie origin details
    CookieOrigin cookieOrigin = context.getCookieOrigin();
    // Cookie spec used
    CookieSpec cookieSpec = context.getCookieSpec();

易踪网:每天进步一点点

转载请保留链接地址: http://www.yeetrack.com/?p=822

时间: 2024-10-21 19:09:51

HttpClient4.3教程 第三章 Http状态管理的相关文章

HttpClient 4.3.6 教程 第3章 HTTP状态管理 【翻译】

转载:http://blog.csdn.net/lianghongge/article/details/42027069 第3章 HTTP状态管理 最初的HTTP被设计成以状态.请求/应答为导向的协议,它被制作成是没有特殊条款的,以便在状态会话中能交换逻辑关系请求/应答.HTTP协议越来越受欢迎和被采用,越来越多的系统会在应用程序里使用它,这是以前所没有想过的,例如电子商务应用程序.因此,对状态管理的支持就十分有必然了. (Netscape Communications)网景公司是当时web客户

HttpClient第三章 HTTP状态管理

原始的HTTP被设置成无状态的面向请求响应的协议,它并没有为基于跨几个逻辑相关的请求/响应交换的有状态会话提供所需的功能.但是随着HTTP协议越来越流行并且被应用,越来越多的系统开始用它作为原本并不是它的作用的功能,例如,电子商务传输应用,这样一来,对于状态管理的支持成为一个必要的功能. 那时网景公司作为一个web客户端和服务器端软件的领导开发者在他们的一个基于特殊的说明的产品里实现了对HTTP状态管理的支持,后来,网景通过发布一个知指导说明书试图标准化这一机制.这些努力促成了通过RFC标准的正

(转)JAVA AJAX教程第三章—AJAX详细讲解

现在开始深入AJAX,这里还是按老思路,理论和实践相结合.这章的内容主要是讲解AJAX步骤详解,下一张将会用一个AJAX技术实现页面提示效果的实例来说明AJAX的实现. 一.AJAX步骤详解 AJAX实质上是遵循Request/Server模式来进行工作的,这个框架基本的流程包括下面几个具体的步骤: (1)       XMLHttpRequest对象初始化 (2)       发送请求 (3)       服务器接收请求并进行处理 (4)       服务器返回响应数据 (5)       客

HttpClient4.3教程 第四章 HTTP认证

HttpClient4.3教程 第四章 HTTP认证 Posted on 2013 年 10 月 17 日 HttpClient既支持HTTP标准规范定义的认证模式,又支持一些广泛使用的非标准认证模式,比如NTLM和SPNEGO. 4.1.用户凭证 任何用户认证的过程,都需要一系列的凭证来确定用户的身份.最简单的用户凭证可以是用户名和密码这种形式.UsernamePasswordCredentials这个类可以用来表示这种情况,这种凭据包含明文的用户名和密码. 这个类对于HTTP标准规范中定义的

HttpClient4.3 教程 第五章 快速API

HttpClient4.3 教程 第五章 快速API Posted on 2013 年 10 月 22 日 5.1.Easy to use facade API HttpClient从4.2开始支持快速api.快速api仅仅实现了HttpClient的基本功能,它只要用于一些不需要灵活性的简单场景.例如,快速api不需要用户处理连接管理和资源释放. 下面是几个使用快速api的例子: // 执行一个get方法,设置超时时间,并且将结果变成字符串 Request.Get("http://www.ye

2018-06-20 中文代码示例视频演示Python入门教程第三章 简介Python

知乎原链 Python 3.6.5官方入门教程中示例代码汉化后演示 对应在线文档: 3. An Informal Introduction to Python 不知如何合集, 请指教. 中文代码示例Python入门教程 3.1.1_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 中文代码示例Python入门教程 3.1.2 第一部分_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 中文代码示例Python入门教程 3.1.2 第二部分_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

Storm入门教程 第三章 Storm安装部署步骤[转]

本文以Twitter Storm官方Wiki为基础,详细描述如何快速搭建一个Storm集群,其中,项目实践中遇到的问题及经验总结,在相应章节以“注意事项”的形式给出. 3.1 Storm集群组件 Storm集群中包含两类节点:主控节点(Master Node)和工作节点(Work Node).其分别对应的角色如下: 1. 主控节点(Master Node)上运行一个被称为Nimbus的后台程序,它负责在Storm集群内分发代码,分配任务给工作机器,并且负责监控集群运行状态.Nimbus的作用类似

python基础教程-第三章-使用字符串

本章将会介绍如何使用字符串何世华其他的值(如打印特殊格式的字符串),并简单了解下利用字符串的分割.联接.搜索等方法能做些什么 3.1 基本字符串操作 所有标准的序列操作(索引.分片.乘法.判断成员资格.求长度.取最小值和最大值)对字符串同样适用,请记住字符串是不可变的. 3.2 字符串格式化:精简版 字符串格式化适用字符串格式化操作符,即百分号%来实现 在%的左侧防止一个字符串(格式化字符串),而右侧则放置希望格式化的值.可以使用一个值,如一个字符串或者数字,也可以使用多个值的元组或者下一张将会

C++教程第三章-数组

转载请注明出处: http://blog.csdn.net/miaoyunzexiaobao PS:命名空间的概念:之前写的std::cout/std::cin/std::endl等,表示cout/cin/endl这些属于一个名为std的命名空间,不愿写的话可以在main之前声明:using namespace std,表明本函数使用命名空间std.命名空间的概念会在以后讲解. 1.      数组的概念 数组是一组类型的值的集合,是由类型名,标识符和维数组成的复合数据类型.其中类型名规定了数组