在Java中将cURL请求转换为HTTP请求

2025/04/11

1. 简介

在使用API时,我们通常首先使用cURL测试请求,cURL是一个命令行工具,可帮助我们轻松发送HTTP请求。在本教程中,我们将介绍几种使用Java将cURL转换为HTTP请求的方法。

2. 了解cURL命令

让我们从一个典型的cURL命令开始:

curl -X POST "http://example.com/api" \
  -H "Content-Type: application/json" \
  -d '{"key1":"value1", "key2":"value2"}'

此命令向URL http://example.com/api发送一个POST请求,具有以下特征:

  • -X POST:指定HTTP方法,使用POST向服务器发送数据
  • -H “Content-Type:application/json”:添加标头,表明请求主体为JSON格式
  • –d ‘{“key1”:”value1”, “key2”:”value2”}’:将有效负载(请求正文)作为包含两个键值对的JSON字符串提供

虽然cURL非常适合测试端点,但将这些命令转换为Java代码可以使我们的API调用可重复使用、可测试,并且能够更好地处理实际项目中的错误;我们可以使用Java中提供的几个不同的库和工具来实现这一点。

3. Java内置的HttpURLConnection

在Java中发出HTTP请求的最简单方法之一是使用HttpURLConnection类,该类内置于Java标准库中。此方法非常简单,不需要任何额外的依赖

下面是如何使用HttpURLConnection将早期的cURL命令转换为Java HTTP请求的示例:

String sendPostWithHttpURLConnection(String targetUrl) {
    StringBuilder response = new StringBuilder();
    try {
        URL url = new URL(targetUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json; utf-8");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);

        String jsonInputString = "{\"key1\":\"value1\", \"key2\":\"value2\"}";

        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = jsonInputString.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        int code = conn.getResponseCode();
        logger.info("Response Code: " + code);

        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(conn.getInputStream(), "utf-8"))) {
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
        }
    } catch (Exception e) {
        // handle exception
    }
    return response.toString();
}

我们首先使用URL类设置连接以创建URL对象,然后使用HttpURLConnection打开一个连接。接下来,我们将请求方法设置为POST,并使用setRequestProperty()添加标头,以指定我们的请求正文是JSON,并且我们期望JSON响应

一旦请求被发送,我们从服务器获取响应码并使用BufferedReader读取响应,将每一行附加到StringBuilder

下面是一个简单的测试用例,当发送有效的POST请求时,它会断言非空响应:

String targetUrl = mockWebServer.url("/api").toString();
String response = CurlToHttpRequest.sendPostWithHttpURLConnection(targetUrl);

assertNotNull(response);
assertFalse(response.isEmpty());
assertEquals("{\"message\": \"Success\"}", response);

4. Apache HttpClient

Apache HttpClient是一个强大且流行的HTTP请求库,它比内置的HttpURLConnection提供更多的控制和灵活性

首先,我们将其依赖添加到pom.xml中:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.4.2</version>
</dependency>

以下是我们使用Apache HttpClient转换cURL请求的方法:

String sendPostRequestUsingApacheHttpClient(String targetUrl) {
    String result = "";
    try (CloseableHttpClient client = HttpClients.createDefault()) {
        HttpPost httpPost = new HttpPost(targetUrl);
        httpPost.setHeader("Content-Type", "application/json");

        String jsonInput = "{\"key1\":\"value1\", \"key2\":\"value2\"}";

        StringEntity entity = new StringEntity(jsonInput);
        httpPost.setEntity(entity);

        try (CloseableHttpResponse response = client.execute(httpPost)) {
            result = EntityUtils.toString(response.getEntity());
            logger.info("Response Code: " + response.getStatusLine().getStatusCode());
        }
    } catch (Exception e) {
        // handle exception
    }
    return result;
}

在此示例中,我们创建一个CloseableHttpClient实例并使用它来对目标URL执行POST请求,我们设置Content-Type标头以指示我们正在发送JSON数据。JSON有效负载包装在StringEntity中并附加到HttpPost请求。执行请求后,我们将响应实体转换为字符串。

Apache HttpClient使我们能够自定义HTTP通信的许多方面,我们可以轻松调整连接超时、管理连接池、添加用于日志记录或身份验证的拦截器以及处理重试或重定向

下面是一个示例,展示了如何自定义Apache HttpClient来设置连接超时并添加一个用于记录请求详细信息的拦截器:

String sendPostRequestUsingApacheHttpClientWithCustomConfig(String targetUrl) {
    String result = "";

    // Create custom configuration for connection and response timeouts.
    RequestConfig config = RequestConfig.custom()
            .setConnectTimeout(Timeout.ofSeconds(10))
            .setResponseTimeout(Timeout.ofSeconds(15))
            .build();

    // Create a custom HttpClient with a logging interceptor.
    CloseableHttpClient client = HttpClientBuilder.create()
            .setDefaultRequestConfig(config)
            .addRequestInterceptorFirst(new HttpRequestInterceptor() {
                @Override
                public void process(HttpRequest request, EntityDetails entity, HttpContext context) {
                    logger.info("Request URI: " + request.getRequestUri());
                    logger.info("Request Headers: " + request.getHeaders());
                }
            })
            .build();

    try {
        HttpPost httpPost = new HttpPost(targetUrl);
        httpPost.setHeader("Content-Type", "application/json");

        String jsonInput = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
        StringEntity entity = new StringEntity(jsonInput);
        httpPost.setEntity(entity);

        try (CloseableHttpResponse response = client.execute(httpPost)) {
            result = EntityUtils.toString(response.getEntity());
            logger.info("Response Code: " + response.getCode());
        }
    } catch (Exception e) {
        // Handle exception appropriately
    } finally {
        // close the client and handle exception
    }
    return result;
}

在这种定制方法中,我们首先创建一个RequestConfig,将连接超时设置为10秒,将响应超时设置为15秒。

此外,我们添加了一个请求拦截器,用于在执行请求之前记录请求URI和标头。此拦截器提供了有关请求详细信息的宝贵见解,这对于调试或监控非常有用

5. OkHttp

OkHttp是Square开发的一款现代HTTP客户端,以易用性和卓越性能而闻名。它支持HTTP/2,广泛应用于Android和Java应用程序

让我们将依赖添加到pom.xml中:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>

下面展示了如何使用OkHttp将cURL请求转换为HTTP请求:

String sendPostRequestUsingOkHttp(String targetUrl) {
    OkHttpClient client = new OkHttpClient();

    MediaType JSON = MediaType.get("application/json; charset=utf-8");

    String jsonInput = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
    RequestBody body = RequestBody.create(jsonInput, JSON);
    Request request = new Request.Builder()
            .url(targetUrl)
            .post(body)
            .build();

    String result = "";
    try (Response response = client.newCall(request).execute()) {
        logger.info("Response Code: " + response.code());
        result = response.body().string();
    } catch (Exception e) {
        // handle exception
    }
    return result;
}

在这段代码中,我们定义一个RequestBody来保存JSON有效负载并指定其内容类型。接下来,我们使用Request.Builder()设置目标URL、HTTP方法(POST)、请求正文和标头。

最后,我们使用client.newCall(request).execute()执行请求,处理可能发生的任何异常。

6. Spring WebClient

此外,在使用Spring框架时,WebClient是一个简化HTTP请求的高级客户端。它是一种现代的非阻塞HTTP客户端,也是在Spring应用程序中发出HTTP请求的推荐方式

我们将cURL示例转换为使用WebClient:

String sendPostRequestUsingWebClient(String targetUrl) {
    WebClient webClient = WebClient.builder()
            .baseUrl(targetUrl)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();

    String jsonInput = "{\"key1\":\"value1\", \"key2\":\"value2\"}";

    return webClient.post()
            .bodyValue(jsonInput)
            .retrieve()
            .bodyToMono(String.class)
            .doOnNext(response -> logger.info("Response received from WebClient: " + response))
            .block();
}

在此示例中,我们创建一个具有目标URL的WebClient实例,并将Content-Type标头设置为application/json。然后,我们使用bodyValue(jsonInput)附加JSON有效负载,此外,我们添加block()以确保该方法同步执行并返回响应。

或者,如果我们在异步或响应式应用程序中工作,我们可以删除block()方法并返回Mono<String>而不是String。

7. 总结

在本文中,我们探讨了如何使用各种库和工具将简单的cURL命令转换为Java代码,HttpURLConnection非常适合我们想要避免外部依赖的简单用例;Apache HttpClient非常适合需要对HTTP请求进行细粒度控制的应用程序。

此外,OkHttp是一款现代HTTP客户端,以其性能而闻名,非常适合微服务或Android开发。Spring WebClient最适合响应式应用程序,尤其是在Spring生态系统中。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章