我正在尝试实现一个通用的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());
});
}
回答“如何返回一个完整的未来”的问题
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); });
查看您的特定代码,thencomposasync
的lambda中似乎存在语法错误(它由两个可完成的未来实例组成,因此其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的值返回给主意图? 主意图代码中的数组列表: 我必须再次将数组列表传递给主要意图吗?像这样: