JAVA:CloseableHttpClient 进行 HTTP 请求的技术指南

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 请求用于从服务器获取资源数据,示例如下:

bash 复制代码
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 数据:

bash 复制代码
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 可以轻松实现文件上传和传递其他表单字段:

bash 复制代码
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 格式:

bash 复制代码
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 请求的响应状态码进行检查,确保服务器返回了预期的结果:

bash 复制代码
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
    // 成功处理逻辑
} else {
    System.err.println("请求失败,状态码:" + statusCode);
}
4.2 连接池和超时设置

为了提高性能,可以使用连接池管理多个 HTTP 连接。此外,设置合理的超时时间对于处理网络延迟也是必要的:

bash 复制代码
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 调用、文件处理等常见应用场景。

相关推荐
XuanXu8 分钟前
Java AQS原理以及应用
java
风象南3 小时前
SpringBoot中6种自定义starter开发方法
java·spring boot·后端
mghio12 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室17 小时前
java日常开发笔记和开发问题记录
java
咖啡教室17 小时前
java练习项目记录笔记
java
鱼樱前端17 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea18 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea18 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
我不会编程55520 小时前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python