You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Jetty HttpClient获取带响应体的CompletableFuture?

使用Jetty发送异步HTTP请求并返回携带完整响应体的CompletableFuture

当然可以实现!Jetty的HttpClient(从Jetty 9.3+开始)就提供了公共API来发送异步请求并返回CompletableFuture,而且完全能拿到完整的响应体——可能你之前看文档的时候没注意到sendAsync()方法的链式处理用法~

核心实现思路

Jetty的Request.sendAsync()默认返回CompletableFuture<Response>,这个Response对象包含了响应头、状态码,以及获取响应体的输入流。我们只需要通过thenApply()链式调用,读取输入流并转换成我们需要的格式(比如字符串),就能得到携带完整响应体的CompletableFuture。

完整代码示例

首先确保你引入了Jetty HttpClient的依赖,然后看下面的代码:

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.util.content.StringContentProvider;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

public class JettyAsyncHttpClientExample {
    private final HttpClient httpClient;

    public JettyAsyncHttpClientExample() throws Exception {
        // 初始化HttpClient
        httpClient = new HttpClient();
        httpClient.start();
    }

    // 发送GET请求,返回携带响应体字符串的CompletableFuture
    public CompletableFuture<String> sendGetRequest(String url) {
        Request request = httpClient.newRequest(url)
                .method(HttpMethod.GET);

        return request.sendAsync()
                .thenApply(response -> {
                    // 读取完整响应体
                    try (InputStream contentStream = response.getContent()) {
                        return new String(contentStream.readAllBytes(), StandardCharsets.UTF_8);
                    } catch (IOException e) {
                        // 包装成CompletionException,符合CompletableFuture的异常处理规范
                        throw new CompletionException("Failed to read response body", e);
                    }
                });
    }

    // 发送POST请求的示例(带请求体)
    public CompletableFuture<String> sendPostRequest(String url, String requestBody) {
        Request request = httpClient.newRequest(url)
                .method(HttpMethod.POST)
                // 设置请求体内容
                .content(new StringContentProvider(requestBody, StandardCharsets.UTF_8));

        return request.sendAsync()
                .thenApply(response -> {
                    try (InputStream contentStream = response.getContent()) {
                        return new String(contentStream.readAllBytes(), StandardCharsets.UTF_8);
                    } catch (IOException e) {
                        throw new CompletionException("Failed to read response body", e);
                    }
                });
    }

    // 记得在应用关闭时停止HttpClient
    public void shutdown() throws Exception {
        httpClient.stop();
    }

    // 测试用例
    public static void main(String[] args) throws Exception {
        JettyAsyncHttpClientExample example = new JettyAsyncHttpClientExample();
        example.sendGetRequest("https://example.com")
                .thenAccept(body -> System.out.println("Response body: " + body))
                .exceptionally(e -> {
                    System.err.println("Request failed: " + e.getMessage());
                    return null;
                })
                // 等待请求完成后关闭客户端
                .thenRun(() -> {
                    try {
                        example.shutdown();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
    }
}

关键注意事项

  • 资源关闭:一定要用try-with-resources包裹响应体的输入流,避免资源泄漏;同时在应用生命周期结束时调用HttpClient.stop()关闭客户端。
  • 异常处理:读取响应体时的IO异常要包装成CompletionException,这样能被CompletableFuture的exceptionally()或handle()方法捕获。
  • 版本兼容:确保使用的Jetty版本是9.3及以上,更早的版本可能没有sendAsync()这个公共API(内部可能用了CompletableFuture但没暴露)。

如果需要处理更复杂的响应体(比如JSON、二进制数据),只需要在thenApply()里替换响应体的解析逻辑即可——比如用Jackson解析JSON,或者直接返回字节数组。

内容的提问来源于stack exchange,提问作者Gili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:57:15