当前位置: 首页 > 知识库问答 >
问题:

如何从CompletableFuture返回CompletableFuture

蒋高杰
2023-03-14

我正在尝试实现一个通用的REST客户端,如下所示。我有自己的模型将HTTP响应表示为response T。这里T是服务调用的返回类型,它可能只是T或Ts列表。下面的代码不编译,我需要帮助。

@Override
    public <T> CompletableFuture<Response<T>> getAsync(UriOptions endpoint, Headers headers) {
        var builder = HttpRequest.newBuilder()
                .uri(endpoint.getAbsoluteUri())
                .GET();
        for (var entry : headers.getMessageHeaders().entrySet()) {
            builder.setHeader(entry.getKey(), entry.getValue());
        }
        var request = builder.build();
        var response = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());

        ObjectMapper objectMapper = new ObjectMapper();
        return response.thenComposeAsync(r ->
            try {
                 new Response<T>(
                        r.statusCode(),
                        HttpUtils.headersToMap(r.headers().map()),
                        objectMapper.readValue(r.body(), new TypeReference<T>() {
                        }),
                        HttpUtils.isSuccess(r.statusCode()), r.uri()
                );
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        );
    }
public class Response<T> {
    private T content;
    private int statusCode;
    private boolean isSuccessful;
    private String statusDescription;
    private Exception exception;
    private Map<String, String> headers;
    private URI uri;

最终调用下面的方法,

@Test
    void getAsync() {
        // Arrange
        var baseUrl = settings.get("api.baseUri");
        var options = new UriOptions(baseUrl, "students/6277aade6f047803e8ae4bcf");
        var headers = new Headers(new HashMap<String, String>(), new HashMap<String, String>());

        // Act
        var response = restApiClient.<Student>getAsync(options, headers);

        // Assert
        response.thenAccept((r) ->
        {
            Assertions.assertEquals(200, r.getStatusCode());
        });
    }

共有1个答案

宗政坚白
2023-03-14

回答“如何返回一个完整的未来”的问题

final CompletableFuture<String> future = CompletableFuture.supplyAsync(() => "42");
final CompletableFuture<Integer> intFuture = future.thenApply(Integer::parseInt);
// or future.thenApply(s -> Integer.parseInt(s));
// or future.thenApply(s -> { return Integer.parseInt(s); });

查看您的特定代码,thencomposasynclambda中似乎存在语法错误(它由两个可完成的未来实例组成,因此其lambda需要返回另一个可完成的未来实例,而不是值本身)。

而且,由于它没有做任何昂贵的工作,因此异步转换值是一种过分的做法。一个简单的然后应用就可以了:

return response.thenApply(r -> {
    try {
         return new Response<T>(
                r.statusCode(),
                HttpUtils.headersToMap(r.headers().map()),
                objectMapper.readValue(r.body(), new TypeReference<T>() {}),
                HttpUtils.isSuccess(r.statusCode()), r.uri()
        );
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
});

如果您坚持使用thenCompose,那么您需要将结果包装在另一个CompletableFuture中:

return response.then(r -> {
    try {
         return CompletableFuture.completedFuture(new Response<T>(
                r.statusCode(),
                HttpUtils.headersToMap(r.headers().map()),
                objectMapper.readValue(r.body(), new TypeReference<T>() {}),
                HttpUtils.isSuccess(r.statusCode()), r.uri()
        ));
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
});
 类似资料:
  • 关于方法何时应该返回CompletableFuture的一般准则是什么?假设有两个类A和B,其中类B有一个执行大量IO的方法performTask(),类A调用performTask()方法在Java可以使用以下方法编写多线程代码: < li >让方法的调用方决定是否使用ThreadPool异步执行方法。在这种情况下,A将异步调用performTask()方法,这样类B就不需要使其方法异步。 <

  • 问题内容: __ 我没有看到一种处理异步结果异常的明显方法。例如,如果我想重试异步操作。我会期望像这样的事情,但是handleAsync并没有按照您认为的那样做- 异步地在另一个线程上运行回调。在这里返回CompletionStage是不正确的。当天的危害问题:就是因为是为了什么? AskPong在哪里问演员: 问题答案: __ 在试图找出用Java 8完成Scala的restoreWith的正确

  • 在构建API时,编写接口代码是一个很好的实践,因此返回CompletionStage似乎是一个最好的方法。然而,我意识到我碰巧总是在获得CompletionStage之后调用.ToCompletableFuture。在这种情况下,推荐的方法是什么?

  • 我有一点奇怪的情况,似乎不允许这个挂钩适合任何广泛建立的CompletableFuture漏洞。 在评估返回布尔值的主要方法中,我希望允许对三个不同方法的调用异步完成。这三个方法中的每一个都可以返回TRUE或FALSE。 如果任何返回FALSE,我希望评估删除余数并简单地返回FALSE值。重点是,它可以是三个中的任何一个,不一定是第一个。 但最重要的是,我需要在实际返回TRUE之前等待所有三个返回

  • 这是我的FegnClient: 这是对外部endpoint的调用: 我得到以下例外: 我的SpringMvcConfig类中确实有一个LocalDateTime转换器

  • 我有一个将arraylist传递给另一个意图的代码,如何将更新后的arraylist的值返回给主意图? 主意图代码中的数组列表: 我必须再次将数组列表传递给主要意图吗?像这样: