欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

httpClient4.2官方文档研究(4)第3章

程序员文章站 2022-03-02 22:30:44
...

原创出处:http://xcxn.iteye.com/blog/1826927

第三章

3. HTTP状态管理

最初的HTTP被设计成一个无状态的,面向请求/响应协议,没有特别规定,有状态会话横跨几个逻辑相关的请求/响应交换。增长的知名度和通过HTTP协议越来越多的系统开始使用它的应用程序,这是从来没有打算,例如电子商务应用的传输。因此,支持状态管理成为必然。

网景通信公司,当时的Web客户端和服务器软件的领先开发商在他们的产品中,实现了支持HTTP状态管理的基础上专有的规范。后来,Netscape发布的规范草案,以规范的机制。这些努力促成正式通过RFC标准跟踪规范定义。然而,一个显着的应用状态管理仍然主要是基于网景公司的草案,是官方的规范不兼容。所有主要的开发人员觉得有必要保留这些应用程序做出了重要贡献符合标准的分散兼容的Web浏览器。

3.1. HTTP cookie的

 HTTP Cookie是可以交换状态信息的HTTP代理和目标服务器保持会话的令牌或短包。使用Netscape工程师为“神奇的饼干”和卡的名称来引用它。

HttpClient的使用Cookie的接口来表示一个抽象的cookie标记。在其最简单的形式中,一个HTTP cookie仅仅是一个名称/值对。通常,一个HTTP Cookie还包含一些属性,如版本,这是有效的域名,这个cookie适用的源服务器上的路径,指定URL的子集,而最长的期限时间的cookie有效的。

SetCookie接口代表一个Set-Cookie响应报头的源服务器发送的HTTP代理,以保持会话状态。 SetCookie2接口扩展SetCookie的具体方法设置Cookie2。

ClientCookie接口扩展Cookie的接口与其他客户的具体功能,如获取原始cookie的属性,正是因为他们被指定由源服务器的能力。生成的Cookie头,这是很重要的,因为一些的cookie规范要求的Cookie头中应包括的某些属性,只有当他们被指定的Set-Cookie或Set-Cookie2头部的。

3.1.1. Cookie的版本

 被认为是版本0的Cookie兼容网景公司的草案规范,但不符合标准的正式规范。符合标准的饼干,预计将有第1版。 HttpClient的处理cookie的版本不同而不同。

下面是重新创建的Netscape 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);
// Set attributes EXACTLY as sent by the server 
stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".mycompany.com");
 下面是一个例子重新创建一个Set-Cookie2兼容的饼干。请注意,符合标准的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);
// Set attributes EXACTLY as sent by the server 
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和可选设置Cookie2的头。

规则的解析cookie验证。

对于一个给定的主机,端口和路径原产地的Cookie头的格式。

HttpClient附带有几个CookieSpec实现:

Netscape draft:符合本规范由Netscape Communications公布的原草案规范。应避免使用,除非绝对必要的遗留代码的兼容性。

RFC 2109:旧版本的官方HTTP状态管理规范RFC 2965所取代。

RFC 2965:官方HTTP状态管理规范。

浏览器兼容性:这个实现努力地模仿常见的网页浏览器应用程序,如Microsoft Internet Explorer和Mozilla Firefox(MIS)的行为。

最佳搭配:“元”拿起cookie政策,格式的HTTP响应发送的cookie的基础上的cookie规范。它基本上聚合了所有以上为一类的实现。

忽略cookie:所有的cookie将被忽略。

我们强烈建议使用最佳匹配策略,让HttpClient拿起一个适当的合规水平,在运行时的执行上下文的基础上。

3.3. HTTP cookie和状态管理参数

 这些参数可用于自定义HTTP状态管理和单独的cookie规范行为:

CookieSpecPNames.DATE_PATTERNS='http.protocol.cookie-datepatterns': 定义要用于解析非标准过期属性的有效日期模式。只需要使用不兼容的服务器仍然使用过期网景公司的草案,而不是标准的max-age属性中定义的兼容。这个参数期望得到一个java.util.Collection类型的值。元素必须是java.lang.String类型兼容的语法java.text.SimpleDateFormat。如果没有设置这个参数的默认值是CookieSpec实现特定的选择。

CookieSpecPNames.SINGLE_COOKIE_HEADER='http.protocol.single-cookie-header': 定义是否应强制成一个单一的Cookie请求头中的Cookie。否则,每个cookie被格式化为一个单独的Cookie头。这个参数期望得到一个java.lang.Boolean类型的值。如果该参数没有设置,选择一个默认值就是CookieSpec具体实施。请注意,此参数只适用于严格的cookie规范(RFC 2109和RFC 2965)。浏览器的兼容性和Netscape的政策草案将始终把所有的cookie到一个请求头。

ClientPNames.COOKIE_POLICY='http.protocol.cookie-policy': 定义一个用于HTTP状态管理的cookie规范的名称。这个参数期望得到一个java.lang.String类型的值。如果该参数没有设置,有效的日期格式是CookieSpec实现特定的。

3.4. Cookie规范注册表

 HttpClient的维护着一个可用的cookie规范注册表的使用CookieSpecRegistry类。默认情况***册每下列规范:

兼容性:浏览器兼容性(宽松政策)。

网景:网景公司的草案。

RFC2109:RFC 2109(过时严格的政策)。

RFC2965:RFC2965(符合标准的严格的政策)。

最佳匹配:匹配元策略。

ignoreCookies:所有的cookie将被忽略。

3.5.选择cookie策略

Cookie策略可以设置在HTTP客户端的HTTP请求级别上覆盖如果需要的话。

用法如下:

HttpClient httpclient = new DefaultHttpClient();
// force strict cookie policy per default
httpclient.getParams().setParameter(
        ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2965);
HttpGet httpget = new HttpGet("http://www.broken-server.com/");
// Override the default policy for this request
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 {
                // Oh, I am easy
            }
        };
    }
};
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getCookieSpecs().register("easy", csf);
httpclient.getParams().setParameter(
     ClientPNames.COOKIE_POLICY, "easy");

 

3.7. Cookie持久性

 HttpClient可以与任何一个持久的cookie存储,实现CookieStore接口的物理表示。称为BasicCookieStore的的默认CookieStore实现的一个简单实现的java.util.ArrayList支持。饼干存储在一个BasicClientCookie对象时,会丢失的容器对象被垃圾收集。如有必要,用户可以提供更复杂的实现。

用法如下:

DefaultHttpClient httpclient = new DefaultHttpClient();
// Create a local instance of cookie store
CookieStore cookieStore = new MyCookieStore();
// Populate cookies if needed
BasicClientCookie cookie = new BasicClientCookie("name", "value");
cookie.setVersion(0);
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// Set the store 
httpclient.setCookieStore(cookieStore);

 

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

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

ClientContext.COOKIESPEC_REGISTRY='http.cookiespec-registry': CookieSpecRegistry http.cookiespec注册表代表实际的cookie规范注册表的实例。此属性的值设置在本地范围内的优先级高于默认的。

ClientContext.COOKIE_SPEC='http.cookie-spec': CookieSpec实例代表实际的cookie规范。

ClientContext.COOKIE_ORIGIN='http.cookie-origin': CookieOrigin实例的原始服务器的实际细节。

ClientContext.COOKIE_STORE='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();
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("http://www.google.com/"); 
// Pass local context as a parameter
HttpResponse response = httpclient.execute(httpget, localContext);