1、简述
CloseableHttpClient 是 Apache HttpComponents 提供的一个强大 HTTP 客户端库。它允许 Java 程序与 HTTP/HTTPS 服务交互,可以发送 GET、POST 等各种请求类型,并处理响应。该库广泛用于 REST API 调用、文件上传和下载等场景。
2、特性
CloseableHttpClient 是 HttpClient 的一个实现类,它可以进行各种 HTTP 请求,并且在使用完毕时支持关闭以释放资源。与其搭配的 HttpResponse 提供了对 HTTP 响应的解析。
主要特性包括:
- 支持同步和异步请求
- 支持连接池和重试机制
- 支持多种请求方法:GET、POST、PUT、DELETE 等
- 支持表单数据、JSON 数据和文件上传等多种数据格式
3、基础用法
3.1 发送 GET 请求
GET 请求用于从服务器获取资源数据,示例如下:
import org.apache.http.HttpEntity;
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;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class HttpClientExample {
public static void main(String[] args) {
// 创建HttpClient实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建GET请求
HttpGet request = new HttpGet("http://httpbin.org/get");
// 执行请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 获取响应体
HttpEntity entity = response.getEntity();
if (entity != null) {
// 将响应体转为字符串
String result = EntityUtils.toString(entity);
System.out.println(result);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 发送 POST 请求
POST 请求用于向服务器提交数据,例如表单数据或 JSON 数据:
import org.apache.http.HttpEntity;
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;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class HttpClientExample {
public static void main(String[] args) {
// 创建HttpClient实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建GET请求
HttpGet request = new HttpGet("http://httpbin.org/get");
// 执行请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 获取响应体
HttpEntity entity = response.getEntity();
if (entity != null) {
// 将响应体转为字符串
String result = EntityUtils.toString(entity);
System.out.println(result);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.3 表单数据和文件上传
在实际开发中,通常会遇到需要上传文件的场景。例如,用户通过网页上传文件到服务器,这时就需要使用 MultipartEntityBuilder 来构建多部分表单(form-data)。
上传文件和表单参数 通过 MultipartEntityBuilder 可以轻松实现文件上传和传递其他表单字段:
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.File;
import java.io.IOException;
import java.util.Map;
public class HttpClientFileUploadWithParams {
public static void main(String[] args) {
// 创建HttpClient实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建POST请求
HttpPost postRequest = new HttpPost("http://httpbin.org/post");
// 模拟表单参数 (key-value 对)
Map<String, String> formParams = Map.of(
"username", "john_doe",
"password", "secret_password"
);
// 构建MultipartEntity,添加文件参数和普通表单参数
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody(
"file", new File("path/to/your/file.txt"),
ContentType.APPLICATION_OCTET_STREAM, "file.txt"
);
// 添加表单参数
for (Map.Entry<String, String> entry : formParams.entrySet()) {
builder.addTextBody(entry.getKey(), entry.getValue(), ContentType.TEXT_PLAIN);
}
// 设置请求体
HttpEntity multipart = builder.build();
postRequest.setEntity(multipart);
// 执行请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
// 获取响应体
String result = EntityUtils.toString(response.getEntity());
System.out.println(result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.4 使用 Map 传递 JSON 数据
如果需要发送 POST 请求并将数据以 JSON 格式发送,可以使用 Map 构建数据并将其序列化为 JSON 格式:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class HttpClientMapJsonExample {
public static void main(String[] args) throws IOException {
// 创建HttpClient实例
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 创建POST请求
HttpPost postRequest = new HttpPost("http://httpbin.org/post");
// 模拟参数 (key-value 对)
Map<String, Object> jsonParams = new HashMap<>();
jsonParams.put("username", "john_doe");
jsonParams.put("age", 30);
jsonParams.put("active", true);
// 将Map转换为JSON字符串
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(jsonParams);
// 设置请求体 (JSON格式)
StringEntity entity = new StringEntity(json);
postRequest.setEntity(entity);
postRequest.setHeader("Content-Type", "application/json");
// 执行请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(postRequest)) {
// 获取响应体
String result = EntityUtils.toString(response.getEntity());
System.out.println(result);
}
}
}
}
4、错误处理和性能优化
4.1错误处理
在使用 CloseableHttpClient 时,建议对 HTTP 请求的响应状态码进行检查,确保服务器返回了预期的结果:
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
// 成功处理逻辑
} else {
System.err.println("请求失败,状态码:" + statusCode);
}
4.2 连接池和超时设置
为了提高性能,可以使用连接池管理多个 HTTP 连接。此外,设置合理的超时时间对于处理网络延迟也是必要的:
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.util.Timeout;
public class HttpClientPoolExample {
public static CloseableHttpClient createHttpClientWithPool() {
// 创建连接池管理器,并设置最大连接数和每个路由的最大连接数
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100); // 最大连接数
connectionManager.setDefaultMaxPerRoute(20); // 每个路由的最大连接数
// 配置请求的超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(10)) // 连接超时时间
.setConnectionRequestTimeout(Timeout.ofSeconds(5)) // 从连接池获取连接的超时时间
.setResponseTimeout(Timeout.ofSeconds(15)) // 请求超时时间
.build();
// 创建带有连接池和请求配置的 HttpClient
return HttpClients.custom()
.setConnectionManager(connectionManager) // 设置连接池管理器
.setDefaultRequestConfig(requestConfig) // 设置请求配置
.build();
}
}
5、总结
通过使用 CloseableHttpClient,可以方便地在 Java 中实现各种 HTTP 请求,包括 GET、POST、文件上传等。在实际开发中,我们可以根据具体业务场景灵活调整请求配置,例如设置超时、使用连接池管理多线程请求等。
这种 HTTP 客户端非常适合 REST API 调用、文件处理等常见应用场景。
评论区