HttpClient 详解
1. HttpClient 简介
HttpClient 是 Apache Jakarta Common 下的子项目,是一个功能强大的 HTTP 客户端工具包。它提供了:
- 支持 HTTP/1.1 和 HTTP/2 协议
- 支持 HTTPS
- 支持代理服务器
- 支持 Cookie 管理
- 支持连接池
- 支持请求重试
- 支持异步请求
2. 核心组件
2.1 主要类说明
-
HttpClient
- 核心类,用于发送 HTTP 请求
- 管理连接池
- 处理请求配置
- 管理 Cookie
-
HttpRequest
- 表示 HTTP 请求
- 常用子类:
HttpGet:GET 请求HttpPost:POST 请求HttpPut:PUT 请求HttpDelete:DELETE 请求
-
HttpResponse
- 表示 HTTP 响应
- 包含状态码
- 包含响应头
- 包含响应体
-
HttpEntity
- 表示 HTTP 消息实体
- 可以是请求体或响应体
- 支持流式处理
-
RequestConfig
- 请求配置类
- 设置超时
- 设置代理
- 设置重定向
3. 基本使用
3.1 创建 HttpClient
// 方式1:使用默认配置
CloseableHttpClient httpClient = HttpClients.createDefault();
// 方式2:自定义配置
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(5000) // 连接超时
.setSocketTimeout(5000) // 读取超时
.setConnectionRequestTimeout(5000) // 从连接池获取连接的超时
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(config)
.build();
3.2 发送 GET 请求
// 创建GET请求
HttpGet request = new HttpGet("https://api.example.com/data");
// 设置请求头
request.setHeader("Content-Type", "application/json");
request.setHeader("Authorization", "Bearer token");
// 执行请求
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 获取响应状态
int statusCode = response.getStatusLine().getStatusCode();
// 获取响应内容
HttpEntity entity = response.getEntity();
String responseBody = EntityUtils.toString(entity);
// 处理响应
if (statusCode == 200) {
// 处理成功响应
}
}
3.3 发送 POST 请求
// 创建POST请求
HttpPost request = new HttpPost("https://api.example.com/data");
// 设置请求头
request.setHeader("Content-Type", "application/json");
// 设置请求体
String jsonBody = "{\"name\":\"test\",\"value\":123}";
StringEntity entity = new StringEntity(jsonBody, "UTF-8");
request.setEntity(entity);
// 执行请求
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 处理响应
}
4. 高级特性
4.1 连接池管理
// 创建连接池管理器
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100); // 最大连接数
cm.setDefaultMaxPerRoute(20); // 每个路由的最大连接数
// 创建HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
4.2 异步请求
// 创建异步HttpClient
CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
httpClient.start();
// 创建异步请求
HttpGet request = new HttpGet("https://api.example.com/data");
// 执行异步请求
Future<HttpResponse> future = httpClient.execute(request, null);
HttpResponse response = future.get(); // 等待响应
4.3 请求重试
// 创建重试策略
HttpRequestRetryHandler retryHandler = (exception, executionCount, context) -> {
if (executionCount >= 3) {
return false;
}
if (exception instanceof InterruptedIOException) {
return false;
}
if (exception instanceof UnknownHostException) {
return false;
}
if (exception instanceof ConnectTimeoutException) {
return true;
}
if (exception instanceof SSLException) {
return false;
}
return true;
};
// 创建HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setRetryHandler(retryHandler)
.build();
5. 最佳实践
5.1 资源管理
-
使用 try-with-resources
try (CloseableHttpClient httpClient = HttpClients.createDefault()) { // 使用httpClient } -
及时关闭响应
try (CloseableHttpResponse response = httpClient.execute(request)) { // 处理响应 }
5.2 性能优化
-
使用连接池
- 避免频繁创建连接
- 合理设置连接池大小
-
启用压缩
request.setHeader("Accept-Encoding", "gzip,deflate"); -
使用持久连接
request.setHeader("Connection", "keep-alive");
5.3 错误处理
-
超时处理
try { response = httpClient.execute(request); } catch (ConnectTimeoutException e) { // 处理连接超时 } catch (SocketTimeoutException e) { // 处理读取超时 } -
重试机制
- 实现自定义重试策略
- 考虑幂等性
6. 常见问题
6.1 连接超时
可能原因:
- 网络不稳定
- 服务器响应慢
- 连接池配置不当
解决方案:
- 调整超时时间
- 实现重试机制
- 优化连接池配置
6.2 内存泄漏
可能原因:
- 未正确关闭资源
- 连接池配置过大
解决方案:
- 使用 try-with-resources
- 及时关闭响应
- 合理配置连接池大小
6.3 性能问题
可能原因:
- 连接池配置不当
- 未启用压缩
- 请求过于频繁
解决方案:
- 优化连接池配置
- 启用压缩
- 实现请求限流