今天开始介绍下Apache HttpClient 4的全面指南,从基础到高级进阶,本文是基础知识一。java
发送Http请求后 - 咱们返回一个org.apache.http.HttpResponse
实例,咱们能够获取到响应的状态行,并隐式地访问状态代码:apache
response.getStatusLine().getStatusCode()
复制代码
使用它,咱们能够验证从服务器收到的代码是不是正确的:安全
@Test
public void test()
throws ClientProtocolException, IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(new HttpGet(SAMPLE_URL));
int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
复制代码
这里面,使用org.apache.http.HttpStatus
中库中提供的预约义状态代码。bash
HttpClient能够配置超时的时间,接下来,咱们看下如何使用。服务器
HttpClient的自带了大量的配置参数,而全部的这些均可以在一个通用的Map集合中来设置。dom
有3个超时参数配置:socket
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));
复制代码
这些参数中更重要的 - 即前两个 - 也能够经过更安全的API进行设置:ide
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
httpParams, timeout * 1000); // http.socket.timeout
复制代码
第三个参数在HttpConnectionParams中没有自定义setter ,它仍然须要经过setParameter方法手动设置。ui
4.3中引入新API来设置超时的方法,这个更方便快捷:spa
int timeout = 5;
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
HttpClientBuilder.create().setDefaultRequestConfig(config).build();
复制代码
这是以类型安全且可读的方式配置全部三个超时的推荐方法。
如今,让咱们解释一下这些不一样类型的超时意味着什么:
前两个参数,connection和socket超时是最重要的。可是,在高负载状况下设置获取链接的超时很是重要,这就是不该忽略第三个参数的缘由。
虽然设置创建HTTP链接和不接收数据的超时很是有用,但有时咱们须要为整个请求设置强制超时。
例如,可能大型文件的下载符合此类别。在这种状况下,能够成功创建链接,数据能够一直经过,可是咱们仍然须要确保操做不会超过某个特定时间阈值。
HttpClient没有任何容许咱们为请求设置总超时的配置; 可是,它确实为请求提供了停止功能,所以咱们能够利用该机制实现一个简单的超时机制:
HttpGet getMethod =new HttpGet("http://localhost:8080/");
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
if (getMethod != null) {
getMethod.abort();
}
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
"HTTP Status of response: " + response.getStatusLine().getStatusCode());
复制代码
咱们正在利用java.util.Timer
和java.util.TimerTask
来设置一个简单的延迟任务,该任务在5秒强制超时后停止HTTP GET请求。
一些较大的域名将使用DNS循环配置是很常见的,基本上具备映射到多个IP地址的相同域名。这引起了针对此类域的超时的新挑战,缘由很简单,由于HttpClient将尝试链接到超时的域:
HttpClient获取到该域的IP路由列表 它尝试第一个 - 超时 它尝试第二个 - 也超时 等等 … 所以,正如你所看到的 - 当咱们指望它时,总体操做不会超时。相反 - 当全部可能的路线超时时它会超时。更重要的是 - 这将彻底透明地发生在客户端上(除非你在DEBUG级别配置了日志)。
这是一个能够运行并复制此问题的简单示例:
int timeout = 3;
RequestConfig config = RequestConfig.custom().
setConnectTimeout(timeout * 1000).
setConnectionRequestTimeout(timeout * 1000).
setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config).build();
HttpGet request =new HttpGet("http://www.domain.com");
response = client.execute(request);
复制代码
你将注意到具备DEBUG日志级别的重试逻辑:
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.212:81 timed out. Connection will be retried using another IP address
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.208:81 timed out. Connection will be retried using another IP address
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...
复制代码
本文介绍了状态码和超时的配置以及机制,但愿对你有所帮助。