一、前言
1、说明
HttpClient是一个目前最常用的用于模拟客户端发送http请求的工具,可用于接口自动化测试或者爬虫或者在项目中加入获取其他网站数据等;
支持目前所有的请求方式,如put,post,get,delete等;
2、maven依赖添加
maven依赖如下:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.6</version>
</dependency>
3、简单的请求说明
如下为一个简单的请求代码:
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class Entry {
public static void main(String[] args) {
CloseableHttpClient client = HttpClients.createDefault();//client实例初始化
HttpGet get = new HttpGet("http://www.baidu.com");//请求初始化
//请求执行,获取返回对象
CloseableHttpResponse response = null;
try {
response = client.execute(get);
System.out.println(response.getStatusLine().getStatusCode());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally
{
try {
response.close();//关闭返回对象
client.close();//关闭client
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以上范例打印结果应为200;
二、httpClient设置
1、httpClient初始化
查看源码可以看到httpClient有如下几种方式:
简单点常用就是createDefault()
方法和custom()
方法;
下面分别对这几种方式做说明:
(1)、createDefault()
此方法返回一个默认的httpClient对象,源码如下:
/**
* Creates {@link CloseableHttpClient} instance with default
* configuration.
*/
public static CloseableHttpClient createDefault() {
return HttpClientBuilder.create().build();
}
进一步查看HttpClientBuilder的源码发现此处使用的是HttpClient4.5已经设置好的一个HttpClient,包括资源池大小,ssl策略,链接管理,cookie等;
(2)、createSystem()
此方法返回一个系统的HttpClient对象,源码如下:
/**
* Creates {@link CloseableHttpClient} instance with default
* configuration based on system properties.
*/
public static CloseableHttpClient createSystem() {
return HttpClientBuilder.create().useSystemProperties().build();
}
查看HttpClientBuilder的源码如下:
/**
* Use system properties when creating and configuring default
* implementations.
*/
public final HttpClientBuilder useSystemProperties() {
this.systemProperties = true;
return this;
}
类的build()中多处根据systemProperties
的值来进行判断,类似如下:
这些都是预设的一些策略。
(3)、createMinimal()
顾名思义,此为最小的HttpClient配置,源代码如下:
/**
* Creates {@link CloseableHttpClient} instance that implements
* the most basic HTTP protocol support.
*/
public static CloseableHttpClient createMinimal() {
return new MinimalHttpClient(new PoolingHttpClientConnectionManager());
}
(4)、createMinimal(final HttpClientConnectionManager connManager)
此项和第三个类似,差别在于此方法的连接控制是自定义的,此处不再详述;
/**
* Creates {@link CloseableHttpClient} instance that implements
* the most basic HTTP protocol support.
*/
public static CloseableHttpClient createMinimal(final HttpClientConnectionManager connManager) {
return new MinimalHttpClient(connManager);
}
(5)、custom()
此方法较为常用,为自定义的配置,可以附加各种配置,源代码如下:
/**
* Creates builder object for construction of custom
* {@link CloseableHttpClient} instances.
*/
public static HttpClientBuilder custom() {
return HttpClientBuilder.create();
}
用法如下所示:
CloseableHttpClient client = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
custom()后面可以加多个配置,记住最后必须加上.build()
;
2、连接配置
自定义初始化HttpClient的时候需要设置连接管理,即上面代码的.setConnectionManager(new PoolingHttpClientConnectionManager())
部分,此方法需要添加的实例为HttpClientConnectionManager
,这个接口有两个实现类,为PoolingHttpClientConnectionManager
和BasicHttpClientConnectionManager
;
BasicHttpClientConnectionManager是一个简单连接管理器,一次只保持一条连接,即便这个类是线程安全的,它也只应该被一个执行线程使用,BasicHttpClientConnectionManager对相同路由的连续请求将重用连接,如果新的连接跟已经持久化保持的连接不同,那么它会关闭已有的连接,根据所给的路由重新开启一个新的连接来使用,如果连接已经被分配出去了,那么java.lang.IllegalStateException异常会被抛出。
该连接管理器的实现应该在EJB容器内使用。一个例子如下;
HttpClientContext context = HttpClientContext.create();
HttpClientConnectionManager connMrg = new BasicHttpClientConnectionManager();
HttpRoute route = new HttpRoute(new HttpHost("localhost", 80));
// Request new connection. This can be a long process
ConnectionRequest connRequest = connMrg.requestConnection(route, null);
// Wait for connection up to 10 sec
HttpClientConnection conn = connRequest.get(10, TimeUnit.SECONDS);
try {
// If not open
if (!conn.isOpen()) {
// establish connection based on its route info
connMrg.connect(conn, route, 1000, context);
// and mark it as route complete
connMrg.routeComplete(conn, route, context);
}
// Do useful things with the connection.
} finally {
connMrg.releaseConnection(conn, null, 1, TimeUnit.MINUTES);
}
PoolingHttpClientConnectionManager是一个更加复杂的实现,其管理了一个连接池,能够为多个执行线程提供连接,连接依据路由归类放入到池中,当一个请求在连接池中有对应路由的连接时,连接管理器会从池中租借出一个持久化连接而不是创建一个带有标记的连接。
PoolingHttpClientConnectionManager在总的和每条路由上都会保持最大数量限制的连接,默认该实现会为每个路由保持2个并行连接,总的数量上不超过20个连接,在现实使用中,这是限制可能太过于苛刻,尤其对于那些将HTTP作为传输协议的服务来说。
下面是一个如何调整连接池参数的例子:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// Increase max total connection to 200
cm.setMaxTotal(200);
// Increase default max connection per route to 20
cm.setDefaultMaxPerRoute(20);
// Increase max connections for localhost:80 to 50
HttpHost localhost = new HttpHost