gpt4 book ai didi

java - 重试 HTTP 请求(Java 11 - HttpClient)

转载 作者:行者123 更新时间:2023-12-04 14:12:57 27 4
gpt4 key购买 nike

问题
使用 HttpClient从 Java 11(JDK,而不是 Apache),我该如何重试请求?
假设我想重试最大 的请求10次​​如果它没有返回 状态码 200或抛出异常。

试图
目前我正在循环重新安排返回的 future ,我想知道是否有更好或更优雅的方式。

CompletableFuture<HttpResponse<Foo>> task = client.sendAsync(request, bodyHandler);

for (int i = 0; i < 10; i++) {
task = task.thenComposeAsync(response -> response.statusCode() == 200 ?
CompletableFuture.completedFuture(response) :
client.sendAsync(request, bodyHandler));
}

// Do something with 'task' ...
如果我们还为特殊情况添加重试,我最终会得到
CompletableFuture<HttpResponse<Foo>> task = client.sendAsync(request, bodyHandler);

for (int i = 0; i < 10; i++) {
task = task.thenComposeAsync(response ->
response.statusCode() == 200 ?
CompletableFuture.completedFuture(response) :
client.sendAsync(request, bodyHandler))
.exceptionallyComposeAsync(e ->
client.sendAsync(request, bodyHandler));
}

// Do something with 'task' ...
不幸的是,似乎没有任何 composeAsync这会同时触发常规完成和异常(exception)。有 handleAsync但它没有 compose , lambda 需要返回 U而不是 CompletionStage<U>那里。

其他框架
为了 QA,我也对展示如何使用其他框架实现这一目标的答案感兴趣,但我不会接受它们。
例如,我看到了一个名为 Failsafe 的库,它可能为此提供了一个优雅的解决方案(参见 jodah.net/failsafe)。

引用
作为引用,这里有一些相关的 JavaDoc 链接:
  • HttpClient
  • CompletableFuture
  • CompletionStage
  • 最佳答案

    我建议按照这些方式做一些事情(假设没有安全管理器):

    public static int MAX_RESEND = 10;

    public static void main(String[] args) {
    HttpClient client = HttpClient.newHttpClient();
    HttpResponse.BodyHandler<String> handler = HttpResponse.BodyHandlers.ofString();
    HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("http://example.com/")).build();
    var response = client.sendAsync(request, handler)
    .thenComposeAsync(r -> tryResend(client, request, handler, 1, r));
    // do something with response...
    }

    public static <T> CompletableFuture<HttpResponse<T>>
    tryResend(HttpClient client, HttpRequest request, BodyHandler<T> handler,
    int count, HttpResponse<T> resp) {
    if (resp.statusCode() == 200 || count >= MAX_RESEND) {
    return CompletableFuture.completedFuture(resp);
    } else {
    return client.sendAsync(request, handler)
    .thenComposeAsync(r -> tryResend(client, request, handler, count+1, r));
    }
    }
    如果您想同时处理常规和异常(exception)情况,您可以执行以下操作:
    public static int MAX_RESEND = 5;

    public static void main(String[] args) {
    HttpClient client = HttpClient.newHttpClient();
    BodyHandler<String> handler = BodyHandlers.ofString();
    HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("http://example.com/")).build();
    CompletableFuture<HttpResponse<String>> response =
    client.sendAsync(request, handler)
    .handleAsync((r, t) -> tryResend(client, request, handler, 1, r, t))
    .thenCompose(Function.identity());
    // do something with response ...
    }

    public static boolean shouldRetry(HttpResponse<?> r, Throwable t, int count) {
    if (r != null && r.statusCode() == 200 || count >= MAX_RESEND) return false;
    if (t instanceof ... ) return false;
    return true;
    }

    public static <T> CompletableFuture<HttpResponse<T>>
    tryResend(HttpClient client, HttpRequest request,
    BodyHandler<T> handler, int count,
    HttpResponse<T> resp, Throwable t) {
    if (shouldRetry(resp, t, count)) {
    return client.sendAsync(request, handler)
    .handleAsync((r, x) -> tryResend(client, request, handler, count + 1, r, x))
    .thenCompose(Function.identity());
    } else if (t != null) {
    return CompletableFuture.failedFuture(t);
    } else {
    return CompletableFuture.completedFuture(resp);
    }
    }

    关于java - 重试 HTTP 请求(Java 11 - HttpClient),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62911377/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com