码迷,mamicode.com
首页 > 其他好文 > 详细

Apache HttpClient : Http Cookies

时间:2014-07-27 23:44:39      阅读:436      评论:0      收藏:0      [点我收藏+]

标签:httpclient   cookies   

前言

HttpClient已经被集成到Android的SDK里,但在JDK里面仍然需要HttpURLConnectionn发起HTTP请求。HttpClient可以看做是一个加强版的HttpURLConnection,但它的侧重点是如何发送请求、接受相应和管理Http连接。


在介绍Http Cookies之前,笔者给出一个应用场景:你需要一个根据地理信息(城市名或者经纬度)获取天气的应用。可选的API很多,不幸的是,网上提到的Google天气API已经停止服务了(不是被墙);雅虎是英文的,且需要得到其城市ID;其他各种知名或不知名的要么收费,要么不好用。实际上,百度推出的车联网API也支持天气服务,不过每个申请的AK原则上访问次数有限(真要做天气应用,推荐使用中国国家气象局的API)。当在百度你申请了AK,发出访问时,可能有这样的提示:

bubuko.com,布布扣

其基本代码如下:

CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet get = new HttpGet("http://api.map.baidu.com/telematics/v3/weather?location=西安&output=json&ak=yourkey");
		CloseableHttpResponse response = httpClient.execute(get);
		System.out.println(EntityUtils.toString(response.getEntity()));
其实,做个爬虫的朋友大多遇到这个警告:Cookie rejected。
好吧。Cookie rejected,下面我们详细讨论HttpClient的Cookie管理机制。


什么是Cookie

一个Http Cookie就是一个令牌或者状态信息的短包,用来在Http代理和目标服务器间维护一个session交互信息。这个名字最早来自于Netscape的工程师。

Httpclient使用Cookie的接口来表示抽象的cookie令牌。它最简单的形式是一个键值对。通常一个Http cookie也包含大量属性,比如版本号,合法的域,在原始服务器上的该cooki起作用的子集URL的路径,cookie存活的最大时间等。

SetCookie接口表示一个由服务器发给Http代理的Set-Cookie响应头,用以维护会话状态。SetCookie2接口继承了SetCookie,并有特定的Set-Cookie2方法。

ClientCookie接口继承了Cookie接口,并添加了额外的特殊功能,比如获取原始的Cookie属性。这对产生Cookie头很重要,因为一些cookie说明要求Cookie头包含只在Set-Cookie或Set-Cookie指定的特定属性。


Cookie版本号

与Netscape草案兼容但不和官方规范兼容的被看做是版本0,标准的兼容cookie被看做是版本1。HttpClient根据版本号可能会以不同方式处理cookie。

下面是一个标准cookie重建的例子。注意:标准兼容cookie必须保留所有来自原始服务器的属性。

BasicClientCookie2 stdCookie = new BasicClientCookie2("name", "value");
stdCookie.setVersion(1);
stdCookie.setDomain(".baidu.com");
stdCookie.setPorts(new int[] {80,8080});
stdCookie.setPath("/");
stdCookie.setSecure(true);
stdCookie.setAttribute(ClientCookie.VERSION_ATTR, "1");
stdCookie.setAttribute(ClientCookie.DOMAIN_ATTR, ".baidu.com");
stdCookie.setAttribute(ClientCookie.PORT_ATTR, "80,8080");


Cookie规范

CookieSpe接口表示一个Cookie管理规范。这个规范有:

  1. Set-Cookie的传递规则和可选的Set-Cookie2头信息
  2. 已传递cookie的验证
  3. 对所给主机、端口和路径的Cookie头的形式

下面有几种Cookie的实现:

Netscape draft:由Netscape委员会发布的原始草案。除非为了绝对的兼容,请避免使用。

Standard:RFC 2965 HTTP 状态管理规范。

Browser compatibility:该实现竭力减小常见浏览器的差异性。

Best match:“元”cookie规范,依据Http响应cookie的格式得到一个cookie规范。基本上集合了上面的所有。

Ignore cookies:忽略所有。

强烈建议使用Best match。


选择cookie 策略

cookie策略可以在Http客户端设置,并在必要时可在Http requset级别上重写。

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("/");
httpGet.setConfig(localConfig);

自定义cookie策略

为了实现一个定制的cookie策略,需要实现CookieSpec接口,创建一个CookieSpeProvier的实现来创建和初始化自定义规范并进行注册。一旦定制的规范完成了注册,它可以像标准的cookie规范一样被激活。

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();

Cookie的持久化

HttpClien可以和任何实现CookieStrore接口的持久化cookie store的物理表示协作。默认的CookieStroe实现是BasicCookie,它是用一个ArrayList实现的。不幸的是,当垃圾回收时存储在BasicClientCookie对象的数据会丢失。

// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// 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
CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultCookieStore(cookieStore)
        .build();


现在HttpClient里面的Cookie的问题基本介绍清楚了。我们使用标准的cookie策略,重新获取天气的代码。

RequestConfig globalConfig = RequestConfig.custom().
				setCookieSpec(CookieSpecs.BEST_MATCH).build();
		
        CloseableHttpClient client = HttpClients.custom().
        		setDefaultRequestConfig(globalConfig).build();
        
        RequestConfig localConfig = RequestConfig.copy(globalConfig)
                .setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY)
                .build();
        HttpGet get = new HttpGet(sb.toString());
        get.setConfig(localConfig);
        
		CloseableHttpResponse response = client.execute(get);
		
		String weatherDetail = EntityUtils.toString(response.getEntity());

返回结果:

bubuko.com,布布扣

Apache HttpClient : Http Cookies,布布扣,bubuko.com

Apache HttpClient : Http Cookies

标签:httpclient   cookies   

原文地址:http://blog.csdn.net/chenloveit/article/details/38179185

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!