您的位置:首页 > 理论基础 > 计算机网络

HttpClient实现网络访问详解

2015-10-24 17:38 609 查看
HttpClient的最常用功能是execute()方法。执行一次execute()会包括了一次或多次request请求
- response响应事件。HttpClient会将request请求发送给目标服务器以取得response响应对象,也可有可能在执行失败后抛出一个异常。

一个简单的代码如下:

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGet httpget = newHttpGet("http://localhost/");

CloseableHttpResponse response = httpclient.execute(httpget);

try {

<...>

} finally {

response.close();

}

2、所有的Http request请求都包括了一个方法名、一个请求地址和一个HTTP协议版本号。HttpClient支持HTTP/1.1协议下所有的HTTP方法,包括:Get、HEAD、POST、PUT、DELETE、TRACE和OPTIONS。每一种方法都通过特定的类来实现,包括HttpGet、HttpHead、HttpPost、HttpPut、HttpDelete、HttpTrace和HttpOptions。

请求地址由一个URI(统一资源定位符)来描述。Http
URI包括了协议、主机名、端口、地址、请求参数等。

例如:

HttpGet httpget = newHttpGet(

"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");

HttpClient 提供了URIBuilder类来简化请求地址的创建和修改,例如:

URI uri = newURIBuilder()

.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://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
3、Httpresponse是服务器返回给客户端的一段报文。报文的第一行包括了协议版本、数字状态码和文字描述。例如:

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

4、一段Http报文包括了多个header描述属性,包括内容长度、内容类型等等,HttpClient提供了查询、删除、处理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\"");

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

最有效率的做法是用HeaderIterator来获得特定类型的所有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\"");

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"

5、HttpEntity 是Http request-reponse交互的报文内容。HttpClient区分了三种报文内容:

(1)流形式的报文内容,报文内容不可重复。

(2)独立的报文内容,报文内容是可重复的。

(3)从其他报文内容中获取的报文内容。

通过HttpEntity的getContent()可以获得Java.io.Inputstream的输入流,也可以通过HttpEntity的writeTo(OutputStream)写入内容。

HttpEntity的getContentType()和getContentLength()方法可以获取Content-Type和Content-Length的元数据,getContentEncoding()方法可以获取编码格式。

例如:

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

输出:

Content-Type:text/plain; charset=utf-8

17

important message

17

读取HttpEntity,例如:

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGet httpget = newHttpGet("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 contentout

}

}

} finally {

response.close();

}

也可以生成报文内容

File file = newFile("somefile.txt");

FileEntity entity = new FileEntity(file,

ContentType.create("text/plain", "UTF-8"));

HttpPost httppost =newHttpPost("http://localhost/action.do");

httppost.setEntity(entity);

6、可以通过UrlEncodeFormEntity来提交表单,例如

List<NameValuePair>formparams = new ArrayList<NameValuePair>();

formparams.add(new BasicNameValuePair("param1","value1"));

formparams.add(new BasicNameValuePair("param2","value2"));

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams,Consts.UTF_8);

HttpPost httppost = newHttpPost("http://localhost/handler.do");

httppost.setEntity(entity);

7、可以采用ResponseHandler来简化连接操作,例如

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpGet httpget = new HttpGet("http://localhost/json");

ResponseHandler<MyJsonObject>rh = new ResponseHandler<MyJsonObject>() {

@Override

public JsonObjecthandleResponse(

final HttpResponse response)throws IOException {

StatusLine statusLine =response.getStatusLine();

HttpEntity entity =response.getEntity();

if (statusLine.getStatusCode()>= 300) {

throw newHttpResponseException(

statusLine.getStatusCode(),

statusLine.getReasonPhrase());

}

if (entity == null) {

throw newClientProtocolException("Response contains no content");

}

Gson gson = newGsonBuilder().create();

ContentType contentType =ContentType.getOrDefault(entity);

Charset charset =contentType.getCharset();

Reader reader = newInputStreamReader(entity.getContent(), charset);

return gson.fromJson(reader,MyJsonObject.class);

}

};

MyJsonObject myjson = client.execute(httpget, rh);

8、 httpClient不是线程安全的,所以如果不再使用的话,可以通过close()方法进行关闭,例如

CloseableHttpClienthttpclient = HttpClients.createDefault();

try {

<...>

} finally {

httpclient.close();

}

9、HttpContext可以作为Http交互的上下文,是以java.util.Map存储的对象。包括了HttpConnection、HttpHost、HttpRoute、HttpRequest等,可以通过HttpclientContext来定义上下文状态。

HttpContext context =<...>

HttpClientContext clientContext =HttpClientContext.adapt(context);

HttpHost target = clientContext.getTargetHost();

HttpRequest request = clientContext.getRequest();

HttpResponse response = clientContext.getResponse();

RequestConfig config = clientContext.getRequestConfig();

10、如果要实现重试机制,可以采用HttpRequestRetryHandler接口来实现。例如:

HttpRequestRetryHandlermyRetryHandler = new HttpRequestRetryHandler() {

public booleanretryRequest(

IOExceptionexception,

intexecutionCount,

HttpContext context){

if (executionCount >= 5){

// Do not retry if over maxretry count

return false;

}

if (exception instanceofInterruptedIOException) {

// Timeout

return false;

}

if (exception instanceofUnknownHostException) {

// Unknown host

return false;

}

if (exception instanceofConnectTimeoutException) {

// Connectionrefused

return false;

}

if (exception instanceofSSLException) {

// SSL handshakeexception

return false;

}

HttpClientContext clientContext =HttpClientContext.adapt(context);

HttpRequest request =clientContext.getRequest();

boolean idempotent = !(requestinstanceof HttpEntityEnclosingRequest);

if (idempotent) {

// Retry if the request isconsidered idempotent

return true;

}

return false;

}

};

CloseableHttpClient httpclient = HttpClients.custom()

.setRetryHandler(myRetryHandler)

.build();

11、重定向处理,例如:

CloseableHttpClienthttpclient = HttpClients.createDefault();

HttpClientContext context = HttpClientContext.create();

HttpGet httpget = newHttpGet("http://localhost:8080/");

CloseableHttpResponse response = httpclient.execute(httpget, context);

try {

HttpHost target =context.getTargetHost();

List<URI> redirectLocations =context.getRedirectLocations();

URI location =URIUtils.resolve(httpget.getURI(), target, redirectLocations);

System.out.println("Final HTTPlocation: " + location.toASCIIString());

// Expected to be an absoluteURI

} finally {

response.close();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: