`

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 4.3 中文版

    HTTP 响应的第一行包含了协议版本、数字状态码及其对应的文本描述。例如,`200 OK` 表示请求成功,`404 Not Found` 表示找不到指定的资源。 **示例代码**: ```java HttpResponse response = new BasicHttpResponse...

    Android 使用HttpClient和第三方MiME文件上传类库,实现文件上传带进度条

    本教程将详细讲解如何利用HttpClient以及第三方MiME(Multipurpose Internet Mail Extensions)文件上传类库,在Android平台上实现文件上传并同时显示进度条。由于HttpClient已经在Android 6.0(API级别23)中被弃用...

    Android HttpClient Network Lib

    在Android中集成HttpClient,首先需要在`build.gradle`文件中添加依赖(对于API 23及以上,由于HttpClient已被弃用,可能需要添加第三方库或使用其他网络库如OkHttp): ```groovy dependencies { implementation ...

    HttpClient以及获取页面内容应用

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

    Android学习之HttpClient练习(一)

    创建HttpClient对象是进行网络请求的第一步。以下代码展示了如何创建一个基本的HttpClient实例: ```java HttpClient httpClient = new DefaultHttpClient(); ``` **3. 设置HTTP请求参数** HttpClient允许我们...

    安卓使用httpClient实现网络请求并通过cookie维持对话

    在Android Studio项目中,由于HttpClient已被弃用,我们需要在build.gradle模块文件中添加一个依赖,通常是添加`androidx.core:core-httpclient`或者使用第三方库如OkHttp。如果选择使用Apache HttpClient,添加...

    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 HttpPost方式获取网页图片

    在Android项目中,通常使用HttpURLConnection或第三方库如OkHttp来处理HTTP请求。对于这个特定的案例,我们可能使用了Apache HttpClient库,因为它支持HttpPost方法。要使用HttpClient,确保在build.gradle文件中...

    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 用户界面开发详解 4.1.1 用户界面...

    Android下通过httpClient发送GET和POST请求的实例代码

    在Android Studio中,由于HttpClient在Android 6.0(API级别23)之后被弃用,因此可能需要添加第三方库如`httpclient-android`或使用其他替代库如OkHttp。但这里我们基于旧版HttpClient来讲解: ```java // 添加...

    HttpUtil,支持data-form、SSL等

    这些jar包可能包含了HTTP客户端库(如Apache HttpClient或OkHttp),SSL相关的库(如Java的JSSE,或者第三方库如Bouncy Castle),以及其他可能的辅助库。 在实际应用中,使用`HttpUtil` 可能包括以下步骤: - ...

    Android SDK开发范例大全(3)

    本资料“Android SDK开发范例大全(3)”聚焦于第3至5章,虽然由于权限限制只能分三次上传,但仍然提供了丰富的知识内容。下面将详细阐述这三章中的关键知识点。 第3章:Android UI设计与布局 3.1 布局管理器:在...

    android利用httppost实现和服务器的通讯

    在Android中,还可以使用第三方库,如Retrofit、Volley、OkHttp等,它们提供了更高级别的封装,使网络请求更加简洁和高效。 总结起来,Android利用HttpPost实现与服务器的通讯涉及网络访问机制、HTTP协议、...

    疯狂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 用户...

Global site tag (gtag.js) - Google Analytics