现在的位置: 首页 > 综合 > 正文

HttpClient 4.3 开发学习(1)

2014年02月04日 ⁄ 综合 ⁄ 共 4921字 ⁄ 字号 评论关闭

HttpComponents Client是现在HttpClient的新版本,是对Commons HttpClient 3.x的继承者和替代品,目前官方强烈推荐升级到新

版本,目前最新版本为HttpClient 4.3.1。好不容易对Commons HttpClient有一点眉目了,现在看HttpComponents Client完全就是一头雾水,不知所云。

HttpComponents Client中一个请求执行的简单模板。

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
    <...>
} finally {
    response.close();
}

HttpComponents Client对HTTP请求方法GETHEADPOSTPUTDELETETRACE and OPTIONS提供相应的类:HttpGetHttpHeadHttpPostHttpPut, HttpDeleteHttpTraceHttpOptions。

HTTP请求行包括一个方法名、请求的URI、HTTP的版本。其中HTTP URI包括a protocol scheme, host name, optional port, resource path, optional
query, and optional fragment。HttpClient 提供了URIBuilder utility
class 来创建和修改请求URI。

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());

HTTP 响应行包含协议的版本、返回状态代码、关联短语。

HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 
HttpStatus.SC_OK, "OK");

System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());

HTTP消息包含一个消息头,描述了消息的内容长度、类型等信息。操作消息头的方法。

HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 
    HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie", 
    "c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie", 
    "c2=b; path=\"/\", c3=c; domain=\"localhost\"");
Header h1 = response.getFirstHeader("Set-Cookie");
System.out.println(h1);
Header h2 = response.getLastHeader("Set-Cookie");
System.out.println(h2);
Header[] hs = response.getHeaders("Set-Cookie");
System.out.println(hs.length);

获取HTTP消息头最有效的方法是使用HeaderIterator迭代器

HeaderIterator it = response.headerIterator("Set-Cookie");

while (it.hasNext()) {
    System.out.println(it.next());
}

同时提供了方便的函数来对消息头进行操作。

HeaderElementIterator it = new BasicHeaderElementIterator(
    response.headerIterator("Set-Cookie"));

while (it.hasNext()) {
    HeaderElement elem = it.nextElement(); 
    System.out.println(elem.getName() + " = " + elem.getValue());
    NameValuePair[] params = elem.getParameters();
    for (int i = 0; i < params.length; i++) {
        System.out.println(" " + params[i]);
    }
}

HTTP消息体会携带一个与请求和响应相关的内容实体。实体是可选的。Request使用entity来封闭请求,HTTP定义了两种实体请求的方法:POST和PUT。Response使用entity来封装一个内容实体。有例外的情况。

HTTPClient根据entity的来源区别了3类实体:

  • Streamed:内容来源于流,或者动态生成。Streamed包括从HTTP Response中接收的实体。通常是不可重复的。
  • Self-contained:自包含的,内容通过独立于其他链接或者实体方法获取。可重复获取使用,通常用来封闭HTTP Request。
  • Wrapping:包装的,内容来源其他实体。

实体重复的意思的实体内容能够被多次读取使用。当创建一个包含内容的请求时,或者当请求成功,响应发送结果给请求时,entity就被创建。

下面是一个StringEntity实例:

package HttpClient4.yang;


import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.ParseException;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;

public class HttpEntity {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			StringEntity entity = new StringEntity("这一个字符串实体", "UTF-8");
			//内容类型
			System.out.println(entity.getContentType());
			//内容的编码格式
			System.out.println(entity.getContentEncoding());
			//内容的长度
			System.out.println(entity.getContentLength());
			//把内容转成字符串
			System.out.println(EntityUtils.toString(entity));
			//内容转成字节数组
			System.out.println(EntityUtils.toByteArray(entity).length);
			//还有个直接获得流
			//entity.getContent();
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		} catch (ParseException e) {
		} catch (IOException e) {
		}

	}

}

资源的释放:

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        InputStream instream = entity.getContent();
        try {
            // do something useful
        } finally {
            instream.close();
        }
    }
} finally {
    response.close();
}

关闭内容流和响应的区别在于:前者通过消费实体内容来保持底层连接,而后者直接关闭并丢弃连接。

消费实体的推荐方法是HttpEntity#getContent() or HttpEntity#writeTo(OutputStream) ,当实体被容需要被多次读取的时候,最好对实体进行缓存,最简单的方法就是通过 BufferedHttpEntity来进行包装

产生实体方法:StringEntityByteArrayEntityInputStreamEntity,
FileEntity

最初,Http被设计成一种无状态的、面向请求-响应的协议。然而,在实际使用中,我们希望能够在一些逻辑相关的请求-响应中,保持状态信息。为了使应用程序可以保持Http的持续状态,HttpClient允许http连接在特定的Http上下文中执行。如果在持续的http请求中使用了同样的上下文,那么这些请求就可以被分配到一个逻辑会话中。HTTP上下文就和一个java.util.Map<String,
Object>
功能类似。它实际上就是一个任意命名的值的集合。应用程序可以在Http请求执行前填充上下文的值,也可以在请求执行完毕后检查上下文。HttpContext可以包含任意类型的对象,因此如果在多线程中共享上下文会不安全。推荐每个线程都只包含自己的http上下文。

在Http请求执行的过程中,HttpClient会自动添加下面的属性到Http上下文中:

  • HttpConnection的实例,表示客户端与服务器之间的连接
  • HttpHost的实例,表示要连接的木包服务器
  • HttpRoute的实例,表示全部的连接路由
  • HttpRequest的实例,表示Http请求。在执行上下文中,最终的HttpRequest对象会代表http消息的状态。Http/1.0和Http/1.1都默认使用相对的uri。但是如果使用了非隧道模式的代理服务器,就会使用绝对路径的uri。
  • HttpResponse的实例,表示Http响应
  • java.lang.Boolean对象,表示是否请求被成功的发送给目标服务器
  • RequestConfig对象,表示http request的配置信息
  • java.util.List<Uri>对象,表示Http响应中的所有重定向地址

HttpClient会被抛出两种类型的异常,一种是java.io.IOException,当遇到I/O异常时抛出(socket超时,或者socket被重置);另一种是HttpException,表示Http失败,如Http协议使用不正确。通常认为,I/O错误时不致命、可修复的,而Http协议错误是致命了,不能自动修复的错误。


抱歉!评论已关闭.