`

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

 
阅读更多



最初,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();

 

分享到:
评论

相关推荐

    HttpClient以及获取页面内容应用

    8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。 9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。 10. 自动处理Set-Cookie中的Cookie。 11....

    Android开发案例驱动教程 配套代码

    第3章 第一个Android程序 15 3.1 HelloAndroid 15 3.1.1 在Eclipse中创建项目 15 3.1.2 编写程序项目代码 17 3.1.3 运行HelloAndroid 18 3.1.4 Android工程目录 19 3.1.5 AndroidManifest.xml文件 21 3.2 ...

    android开发揭秘PDF

    第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户...

    《Android应用开发揭秘》附带光盘代码.

     第3章 Android程序设计基础  3.1 Android程序框架  3.1.1 Android项目目录结构  3.1.2 Android应用解析  3.2 Android的生命周期  3.3 Android程序U设计  3.4 小结  第4章 用户界面开发  4.1 用户界面开发...

    《Android应用开发揭秘》源码

     第3章 Android程序设计基础  3.1 Android程序框架  3.1.1 Android项目目录结构  3.1.2 Android应用解析  3.2 Android的生命周期  3.3 Android程序U设计  3.4 小结  第4章 用户界面开发  4.1 用户界面开发...

    疯狂Android讲义源码

     第3章 事件处理 144  3.1 Android的事件处理 145  3.2 基于监听的事件处理 145  3.2.1 事件监听的处理模型 145  3.2.2 事件和事件监听器 148  3.2.3 内部类作为事件监听器类 151  3.2.4 外部类作为事件监听...

    Android应用开发揭秘pdf高清版

    第3章 Android程序设计基础 3.1 Android程序框架 3.1.1 Android项目目录结构 3.1.2 Android应用解析 3.2 Android的生命周期 3.3 Android程序U设计 3.4 小结 第4章 用户界面开发 4.1 用户界面开发详解 4.1.1 用户...

    疯狂Android讲义.part1

    第3章 事件处理 144 3.1 Android的事件处理 145 3.2 基于监听的事件处理 145 3.2.1 事件监听的处理模型 145 3.2.2 事件和事件监听器 148 3.2.3 内部类作为事件监听器类 151 3.2.4 外部类作为事件监听器类 152 3.2.5 ...

    精通ANDROID 3(中文版)1/2

    第3章 使用Android资源  3.1 资源  3.1.1 字符串资源  3.1.2 布局资源  3.1.3 资源引用语法  3.1.4 定义资源ID供以后使用  3.1.5 已编译和未编译的Android资源  3.2 Android关键资源  3.3 使用任意...

    精通Android 3 (中文版)2/2

    第3章 使用Android资源  3.1 资源  3.1.1 字符串资源  3.1.2 布局资源  3.1.3 资源引用语法  3.1.4 定义资源ID供以后使用  3.1.5 已编译和未编译的Android资源  3.2 Android关键资源  3.3 使用任意...

    OPhone应用开发权威指南(黄晓庆)

    第3章 OPhone应用程序模型 35 3.1 OPhone应用程序基础 35 3.1.1 OPhone应用程序运行环境 35 3.1.2 OPhone应用程序的组成 36 3.2 Activity 43 3.2.1 Activity创建与声明 44 3.2.2 Activity的生命周期 48 3.2.3 启动...

    开涛高可用高并发-亿级流量核心技术

    第3部分高并发 153 9 应用级缓存 154 9.1 缓存简介 154 9.2 缓存命中率 155 9.3 缓存回收策略 155 9.3.1 基于空间 155 9.3.2 基于容量 155 9.3.3 基于时间 155 9.3.4 基于Java对象引用 156 9.3.5 回收算法 156 9.4 ...

Global site tag (gtag.js) - Google Analytics