HttpClient的最重要的功能是执行HTTP方法。一个HTTP方法的执行涉及到一个或多个HTTP请求或HTTP响应的交流,HttpClient通常是在内部处理的。用户将提供一个执行请求对象,HttpClient发送请求到目标服务器返回一个相应的响应对象,如果执行失败则抛出一个异常。所以,HttpClient API的主要切入点是HttpClient的接口,它定义了上述约定。
下面是一个请求执行过程中的最简单形式的例子:
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int l;
byte[] tmp = new byte[2048];
while ((l = instream.read(tmp)) != -1) {
}
}
所有的HTTP请求包含一个由请求行组成的一个方法名,一个请求的URI和一个HTTP协议的版本。
HttpClient的支持在HTTP/1.1规范中定义的所有的HTTP方法:GET, HEAD, POST, PUT, DELETE, TRACE 和 OPTIONS。每有一个方法都有一个对应的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace和HttpOptions。所有的这些类均实现了HttpUriRequest接口,故可以作为execute的执行参数使用。请求URI是能够应用请求的统一资源标识符。 HTTP请求的URI包含一个协议计划protocol scheme,主机名host name,,可选的端口optional port,资源的路径resource path,可选的查询optional query和可选的片段optional fragment。
HttpGet httpget = new HttpGet(
"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
HttpClient提供了一系列实用的方法来简化创建和修改请求URI。
URI可以组装编程:
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
"q=httpclient&btnG=Google+Search&aq=f&oq=", null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
输出>
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
查询字符串也可以通过添加参数列表来生成:
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("q", "httpclient"));
qparams.add(new BasicNameValuePair("btnG", "Google Search"));
qparams.add(new BasicNameValuePair("aq", "f"));
qparams.add(new BasicNameValuePair("oq", null));
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
URLEncodedUtils.format(qparams, "UTF-8"), null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
输出>
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
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/1.1
200
OK
HTTP/1.1 200 OK
一个HTTP消息可以包含一系列headers参数描述信息,例如内容长度,内容类型等。 HttpClient的提供方法来检索,添加,删除和枚举headers。
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);
输出>
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
2
最有效获取所有的给定类型的headers方式是使用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());
}
输出>
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
它还提供了方便的方法来解析HTTP消息的单个header元素
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]);
}
输出>
c1 = a
path=/
domain=localhost
c2 = b
path=/
c3 = c
domain=localhost
HTTP消息的可以进行内容实体和请求或响应关联。可以在一些要求和一些回应中找到实体,因为它们是可选的。实体内附与请求之中。 HTTP规范定义了两个实体内附方法:POST和PUT。响应通常将会附上一个内容实体。但是响应HEAD方法和 204 No Content, 304 Not Modified, 205 Reset Content responses 除外。
HttpClient的区分三种不同实体的地方在于内容来源于:
streamed流媒体:内容是从收到的流,或在运行中产生的。特别是包括被从HTTP响应收到的实体。流媒体的实体一般不可重复。
self-contained独立的:内容是在内存或以从一个连接或其他实体的独立获得的。独立的的实体,一般可重复的。这种类型的实体将主要用于内附在HTTP请求中。
wrapping包装:实体内容是从另一个实体获得。
当得到一个HTTP响应流的内容的时候,这种区分对于连接管理是很重要的。对于请求实体,通过应用程序来创建和只通过使用的HttpClient发送,流和自载之间差别很小。在这种情况下,建议考虑非重复的流实体,以及那些重复的自载实体。
一个实体可以是可重复的,这意味着它的内容可以被读取一次以上。唯一有可能是的独立的实体(如ByteArrayEntity或StringEntity())
由于一个实体能够表示二进制和字符的内容,它可以提供编码的支持(支持文字、IE和字符内容)。
这个实体在执行封闭内容的请求的时候或者在请求成功和响应返回成功的时候被创建。
若要读取从实体内容,一可以通过检索HttpEntity#getContent()方法,它返回一个java.io.InputStream,或一个可以提供一个输出流的HttpEntity#writeTo(OutputStream中)方法的输入流,这将返回已被写入给定的流的所有内容。
当通过传入的消息收到实体,方法HttpEntity#getContentType()和HttpEntity#getContentLength()方法可用于阅读通用元数据metadata,如Content-Type,Content-Length headers(如果可用)。由于Content-Type header可以包含一个像text/plain或者text/html的文本mime-types的character encoding,HttpEntity#getContentEncoding()方法用来读取此信息。如果headers是不可用,返回的长度是-1,content type并为NUL。如果Content – Type header可用,将返回一个header对象。
当创建了一个即将卸任的消息实体,该meta data必须提供由该实体的创造者。
StringEntity myEntity = new StringEntity("important message",
"UTF-8");
System.out.println(myEntity.getContentType());
System.out.println(myEntity.getContentLength());
System.out.println(EntityUtils.getContentCharSet(myEntity));
System.out.println(EntityUtils.toString(myEntity));
System.out.println(EntityUtils.toByteArray(myEntity).length);
stdout >
Content-Type: text/plain; charset=UTF-8