1.request
HttpClient最重要的功能就是就是执行Http的方法。执行Http方法设计一个或多个http request和http response ,这些通常由HttpClient内部处理,用户提供一个待执行request的对象,HttpClient将把request发送到目标服务器并返回响应的response对象,或者在执行失败的情况下抛出异常。
所以,HttpClient API主要的入口定义了就是上述内容的httpClient接口,for example
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
<...>
response.close();
}
所有HTTP请求行包含方法名,请求URI和HTTP协议版本。HttpClient支持HTTP / 1.1规范中定义的所有HTTP方法:get,post,put,delete等,每一个特定的类都有一个特定的方法与之对应,:HttpHead HttpGet HttpPost、HttpPut HttpDelete HttpTrace,HttpOptions。
HttpGet httpget = new HttpGet(
"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
HttpClient也提供了URIBuilder类来简化创建和修改请求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);
2.request 执行
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());
3.处理消息头
一个Http消息可以包含多个描述属性信息的头,如,内容长度,内容类型,HttpClient提供了一些方法来检索、添加、删除和列举头。
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);
获得给定类型的所有头文件最有效的方式是HeaderIterator接口。
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\"");
HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
System.out.println(it.next());
}
还有一种方法是HeaderElementInterator
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\"");
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]);
}
}
1.4 Http实体
HTTP消息可以携带一个内容实体相关的请求或响应。实体中可以找到一些请求和响应,因为它们是可选的。要求使用包含实体被称为实体的请求。HTTP规范定义了两个实体封闭请求方法:POST和PUT。反应通常会附上一个内容的实体。
一个实体可以是可重复的,这意味着它的内容可以读过不止一次。这仅仅是可能与自包含实体(比如ByteArrayEntity或StringEntity)
StringEntity myEntity = new StringEntity("important message",
ContentType.create("text/plain", "UTF-8"));
System.out.println(myEntity.getContentType());
System.out.println(myEntity.getContentLength());
System.out.println(EntityUtils.toString(myEntity));
System.out.println(EntityUtils.toByteArray(myEntity).length);
1.5 释放资源
为了确保适当的释放系统资源必须密切与实体相关联的内容流或反应本身
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();
}
关闭内容流之间和关闭response的区别是前者将试图让底层连接活着,我们可以通过使用实体内容而后者立即关闭和丢弃的连接。
1.6 消费实体内容
推荐使用一个实体的内容的方法是利用其HttpEntity # getContent()或HttpEntity #writeTo(OutputStream)方法。HttpClient还带有EntityUtils的类,它暴露了一些静态方法更容易阅读的内容或信息从一个实体。而不是阅读io。InputStream直接,一个可以检索整个内容的身体在一个字符串和字节数组通过使用从这个类的方法。然而,不提倡使用EntityUtils除非响应实体来自受信任的HTTP服务器和已知的有限的长度。
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
System.out.println(EntityUtils.toString(entity));
} else {
// Stream content out
}
}
} finally {
response.close();
}
在某些情况下可能需要不止一次能够阅读实体内容。在这种情况下,实体内容必须以某种方式缓冲,在内存或磁盘上。最简单的方式来完成,通过包装原始实体BufferedHttpEntity类。这将导致原始实体的内容读取到内存缓冲区。在所有其他方面,将原来的一个实体包装器。
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file,ContentType.create("text/plain", "UTF-8"));
HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);
请注意InputStreamEntity是不可重复的,因为它只能从底层数据流读取一次。一般建议来实现一个自定义HttpEntity类是独立的而不是使用通用InputStreamEntity。FileEntity可以是一个很好的起点。