![](/img/trans.png)
[英]Merge two api responses into one using Webclient - Webflux
[英]Merge two responses
firstResponse
和secondResponse
應該組合成CombinationBothResponses
並在調用 GET 端點127.0.0.1:8081/comb
時返回。 但是,第一次調用時會返回正確組合的響應:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit ...",
"bodySecondResponse": "est rerum tempore ..."
}
但只有 firstResponse 在所有進一步的調用中返回:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit ...",
"bodySecondResponse": null
}
如何始終返回組合響應?
@RestController
public class Controller {
@Autowired Service service;
@GetMapping("/comb")
public CompletableFuture<CombinationBothResponses> combine() {
CompletableFuture<CombinationBothResponses> resultCallback = new CompletableFuture<>();
service.sendTwoRequests(resultCallback);
return resultCallback;
}
}
@org.springframework.stereotype.Service
public class Service {
private final Jsonb jsonb = JsonbBuilder.create();
private final OkHttpClient client = new OkHttpClient();
public void sendTwoRequests(CompletableFuture<CombinationBothResponses> resultCallback) {
// 1. Send GET request 1
Request firstRequest =
new Request.Builder().url("https://jsonplaceholder.typicode.com/posts/1").build();
client.newCall(firstRequest).enqueue(new firstCallback(resultCallback));
// 2. Send GET request 2
Request secondRequest =
new Request.Builder().url("https://jsonplaceholder.typicode.com/posts/2").build();
resultCallback.thenAccept(
firstResponse -> {
client.newCall(secondRequest).enqueue(new secondCallback(resultCallback));
});
}
}
public class firstCallback implements Callback {
private final Jsonb jsonb = JsonbBuilder.create();
private final CompletableFuture<CombinationBothResponses> resultCallback;
public firstCallback(CompletableFuture<CombinationBothResponses> resultCallback) {
this.resultCallback = resultCallback;
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
var firstResponse = jsonb.fromJson(response.body().string(), CombinationBothResponses.class);
if (response.isSuccessful()) {
resultCallback.complete(firstResponse);
} else {
resultCallback.completeExceptionally(new RuntimeException());
}
}
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
resultCallback.completeExceptionally(e);
}
}
public class secondCallback implements Callback {
private final Jsonb jsonb = JsonbBuilder.create();
private final CompletableFuture<CombinationBothResponses> resultCallback;
public secondCallback(CompletableFuture<CombinationBothResponses> resultCallback) {
this.resultCallback = resultCallback;
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
var secondResponse = jsonb.fromJson(response.body().string(), CombinationBothResponses.class);
if (response.isSuccessful()) {
// 3. Combine firstResponse and secondResponse to the final response of the REST
// controller
resultCallback.thenApply(
firstResponse -> {
firstResponse.setBodySecondResponse(secondResponse.getBody());
System.out.println(firstResponse.getBodySecondResponse() != null); // true
return firstResponse;
});
} else {
resultCallback.completeExceptionally(new RuntimeException());
}
}
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
resultCallback.completeExceptionally(e);
}
}
@Data
@NoArgsConstructor
public class CombinationBothResponses {
private int userId;
private int id;
private String title;
private String body;
private String bodySecondResponse;
}
當你調用resultCallback.complete(firstResponse);
在firstCallback
中,您完成了在控制器中發起的請求。
為什么第一次答案是正確的可能取決於第一次請求在代碼到達thenApply
on the secondCallback
之前第一次完成的速度。 (之后,也許緩存使第一個請求完成得更快,代碼沒有時間到達thenApply
)。
您需要在每個返回CompletableFuture
的方法中拆分兩個請求,然后在更高級別使用thenApply
或thenCombine
來鏈接兩個請求。
看看我之前提供的類似答案r。
創建 2 個不同的可完成供應商,然后將它們組合並返回最終組合的 object。
例如:
//Async supplier for the api calls
CompletableFuture<ResponseType1> cf1 = CompletableFuture.supplyAsync(() -> method(returnSyncResponseType1);
CompletableFuture<ResponseType2> cf2 = CompletableFuture.supplyAsync(() -> returnSyncResponseType2);
//composing result for these async supplier
CompleteableFuture.allOf(resp1, resp2).thenApply(new ComposedResponse(cf1.join, cf2.join));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.