簡體   English   中英

合並兩個響應

[英]Merge two responses

firstResponsesecondResponse應該組合成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的方法中拆分兩個請求,然后在更高級別使用thenApplythenCombine來鏈接兩個請求。

看看我之前提供的類似答案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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM