0Pricing
Java Academy · 课时

错误处理与异步 HTTP 流水线

使用 exceptionally、handle 和 whenComplete 处理错误,然后构建异步 HTTP 客户端流水线

错误处理与异步 HTTP 流水线 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

为什么异步错误处理很重要

在异步流程中,异常的传播方式与同步代码不同。您必须使用 exceptionally、handle 或 whenComplete 显式处理错误。

exceptionally:从错误中恢复

exceptionally(Function<Throwable, T>) 仅在异步任务以异常完成时调用。它会提供一个备用值,让处理流水线继续运行。

CompletableFuture<String> safe = fetchUser(id)
    .thenApply(User::getName)
    .exceptionally(ex -> {
        log.warn("Fetch failed: " + ex.getMessage());
        return "Anonymous";
    });
System.out.println(safe.join()); // "Anonymous" if fetch failed

handle:转换成功与失败结果

handle(BiFunction<T, Throwable, U>) 在成功和失败时都会调用。两个参数中有一个将为 null。

fetchUser(id).handle((user, ex) -> {
    if (ex != null) return UserDto.empty();
    return UserDto.from(user);
}).thenAccept(dto -> sendResponse(dto));

whenComplete:任意结果后的副作用

whenComplete(BiConsumer) 在完成后无论结果如何都会调用。它不会改变结果——请将其用于日志记录、指标记录或清理。

fetchUser(id)
    .whenComplete((user, ex) -> {
        if (ex != null) metrics.increment("user.fetch.error");
        else            metrics.increment("user.fetch.success");
    })
    .thenAccept(u -> sendResponse(u));

重试失败的异步任务

通过在失败时递归调用该操作来实现重试逻辑,直到达到最大尝试次数。

CompletableFuture<String> withRetry(Supplier<CompletableFuture<String>> task, int retries) {
    return task.get().exceptionallyCompose(ex -> {
        if (retries > 0) {
            System.out.println("Retrying... " + retries);
            return withRetry(task, retries - 1);
        }
        return CompletableFuture.failedFuture(ex);
    });
}

Java 11 HttpClient:异步 GET

Java 11 的 HttpClient 通过 sendAsync() 提供完全异步的 HTTP 请求,并返回 CompletableFuture<HttpResponse<String>>。

HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .build();
CompletableFuture<String> body = client
    .sendAsync(req, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body);

串联多个 HTTP 调用

请使用 thenCompose 串联有依赖关系的 HTTP 调用:先获取用户,再使用用户的 ID 获取其订单。

client.sendAsync(userReq, HttpResponse.BodyHandlers.ofString())
    .thenApply(r -> parseUser(r.body()))
    .thenCompose(user -> client.sendAsync(
        buildOrdersRequest(user.getId()),
        HttpResponse.BodyHandlers.ofString()))
    .thenApply(r -> parseOrders(r.body()))
    .thenAccept(orders -> System.out.println("Orders: " + orders.size()));

使用 allOf 并行执行 HTTP 调用

并行调用多个端点,然后在全部完成后收集所有响应。

List<URI> endpoints = List.of(uri1, uri2, uri3);
List<CompletableFuture<String>> requests = endpoints.stream()
    .map(uri -> client.sendAsync(
            HttpRequest.newBuilder(uri).build(),
            HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body))
    .collect(Collectors.toList());
List<String> responses = CompletableFuture
    .allOf(requests.toArray(new CompletableFuture[0]))
    .thenApply(v -> requests.stream().map(CompletableFuture::join).collect(Collectors.toList()))
    .join();

HTTP 调用超时

请直接对异步 HTTP 调用应用 orTimeout,这样服务器响应时间过长时就会取消该调用。

CompletableFuture<String> result = client
    .sendAsync(req, HttpResponse.BodyHandlers.ofString())
    .orTimeout(5, TimeUnit.SECONDS)
    .thenApply(HttpResponse::body)
    .exceptionally(ex -> "timeout or error");

在流水线中验证状态码

请使用 thenApply 检查 HTTP 状态码;如果状态码表示错误,则抛出领域异常,从而保持流水线的错误处理一致。

.thenApply(response -> {
    if (response.statusCode() != 200)
        throw new HttpResponseException(response.statusCode());
    return response.body();
})

组合错误恢复与日志记录

在同一条流水线中,用 whenComplete 记录日志,用 exceptionally 进行恢复——两者可以自然组合。

fetchData()
    .whenComplete((r, ex) -> { if (ex != null) log.error("Failed", ex); })
    .exceptionally(ex -> fallback())
    .thenAccept(result -> process(result));

快速检查

哪个 CompletableFuture 方法仅在异步任务失败时调用?

回顾

使用 exceptionally 提供备用值,使用 handle 转换成功和失败两种结果,使用 whenComplete 执行副作用。使用 Java 11 HttpClient、thenCompose 和 allOf 构建异步 HTTP 流水线。

常见问题解答

「错误处理与异步 HTTP 流水线」课时是免费的吗?

是的 — 「错误处理与异步 HTTP 流水线」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「错误处理与异步 HTTP 流水线」这节课中我会学到什么?

使用 exceptionally、handle 和 whenComplete 处理错误,然后构建异步 HTTP 客户端流水线 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「错误处理与异步 HTTP 流水线」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 创建和完成 CompletableFutures
  2. 使用 thenApply 和 thenCompose 链式处理
  3. 组合 Future:allOf 与 anyOf
  4. 错误处理与异步 HTTP 流水线
← 返回 Java Academy