完整future:如何将两个异步请求组合到一个响应中

发布于 2025-02-02 02:58:22 字数 5078 浏览 3 评论 0原文

第一个请求是异步发送的,然后从对第一个请求的响应中获取ID值,并在第二个异步请求中使用。然后将两个对请求1和请求2的响应组合在一起。下面的示例有效,但不是异步,因为使用.get()。有没有办法不同步? 简

​端点“/组合”通过后方法:

{ “用户ID”:1, “ id”:2, “标题”:“ 3”, “身体”:“ 4”}

@RestController
public class CombinationController {
    @Autowired
    CombinationService combinationService;

    @PostMapping("/combine")
    public CompletableFuture<CombinationBothResponses> combine(@RequestBody RequestBodyOne requestBodyOne) {
        return combinationService.combine(requestBodyOne);
    }
}
@Service
public class CombinationService {
    private final Jsonb jsonb = JsonbBuilder.create();
    private final HttpClient httpClient = HttpClient.newBuilder().build();

    public CompletableFuture<CombinationBothResponses> combine(RequestBodyOne requestBodyOne) {
        // 1. Send POST request 1
        HttpRequest httpRequestOne =
                HttpRequest.newBuilder(URI.create("https://jsonplaceholder.typicode.com/posts"))
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .POST(HttpRequest.BodyPublishers.ofString(jsonb.toJson(requestBodyOne)))
                        .build();

        return httpClient
                .sendAsync(httpRequestOne, HttpResponse.BodyHandlers.ofString())
                .thenApply(
                        httpResponse -> {
                            if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
                                CombinationBothResponses combinationBothResponses =
                                        jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
                                // 2. Use one value from response 1 for request 2
                                int valueToBeUsedInRequestBody2 = combinationBothResponses.getId();
                                // 3. Send POST request 2
                                CompletableFuture<CombinationBothResponses> completableFuture2 =
                                        sendSecondPostRequest(valueToBeUsedInRequestBody2);
                                // 4. Combine response 1 and response 2 to the final response of REST controller
                                try {
                                    CombinationBothResponses responseBodyRequestTwo =
                                            completableFuture2.get(); // Not asynchronous
                                    combinationBothResponses.setSuccess(responseBodyRequestTwo.getSuccess());
                                    return combinationBothResponses;

                                } catch (InterruptedException | ExecutionException e) {
                                    e.printStackTrace();
                                }
                            }
                            throw new RuntimeException();
                        });
    }

    private CompletableFuture<CombinationBothResponses> sendSecondPostRequest(
            int valueToBeUsedInRequestBody2) {
        RequestBodyTwo requestBodyTwo = new RequestBodyTwo(valueToBeUsedInRequestBody2, "request 2");
        HttpRequest httpRequest =
                HttpRequest.newBuilder(URI.create("https://reqbin.com/echo/post/json"))
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .POST(HttpRequest.BodyPublishers.ofString(jsonb.toJson(requestBodyTwo)))
                        .build();

        return httpClient
                .sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
                .thenApply(
                        httpResponse -> {
                            if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
                                CombinationBothResponses responseBodyRequestTwo =
                                        jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
                                return responseBodyRequestTwo;
                            }
                            throw new RuntimeException();
                        });
    }
}
@Data
@NoArgsConstructor
public class RequestBodyOne {
    private int userId;
    private int id;
    private String title;
    private String body;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestBodyTwo {
    private int id;
    private String key;
}
@Data
@NoArgsConstructor
public class CombinationBothResponses {
    private int userId;
    private int id;
    private String title;
    private String body;

    private String success;

}

对请求1的响应:

{“ userId”:0,“ id”:101,“ title”:“ 3”,“身体”:“ 4”}

对请求2:

{“成功”:“ true”}

组合响应; REST控制器的响应:

{ “用户”:0, “ id”:101, “标题”:“ 3”, “身体”:“ 4”, “成功”:“ true”}

The first request is sent asynchronously, then the id value is taken from the response to the first request and used in the second asynchronous request. And then both responses to request 1 and request 2 are combined. The example below works, but is not asynchronous because .get() is used. Is there a way to do this asynchronously?
The process in short - everything should happen asynchronously:

  1. Send POST request 1
  2. Use the id value from response 1 for request 2
  3. Send POST request 2
  4. Combine response 1 and response 2 to the final response of the REST controller

This body is sent to the REST controller endpoint "/combine" via POST method:

{
"userid": 1,
"id": 2,
"title": "3",
"body": "4" }

@RestController
public class CombinationController {
    @Autowired
    CombinationService combinationService;

    @PostMapping("/combine")
    public CompletableFuture<CombinationBothResponses> combine(@RequestBody RequestBodyOne requestBodyOne) {
        return combinationService.combine(requestBodyOne);
    }
}
@Service
public class CombinationService {
    private final Jsonb jsonb = JsonbBuilder.create();
    private final HttpClient httpClient = HttpClient.newBuilder().build();

    public CompletableFuture<CombinationBothResponses> combine(RequestBodyOne requestBodyOne) {
        // 1. Send POST request 1
        HttpRequest httpRequestOne =
                HttpRequest.newBuilder(URI.create("https://jsonplaceholder.typicode.com/posts"))
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .POST(HttpRequest.BodyPublishers.ofString(jsonb.toJson(requestBodyOne)))
                        .build();

        return httpClient
                .sendAsync(httpRequestOne, HttpResponse.BodyHandlers.ofString())
                .thenApply(
                        httpResponse -> {
                            if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
                                CombinationBothResponses combinationBothResponses =
                                        jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
                                // 2. Use one value from response 1 for request 2
                                int valueToBeUsedInRequestBody2 = combinationBothResponses.getId();
                                // 3. Send POST request 2
                                CompletableFuture<CombinationBothResponses> completableFuture2 =
                                        sendSecondPostRequest(valueToBeUsedInRequestBody2);
                                // 4. Combine response 1 and response 2 to the final response of REST controller
                                try {
                                    CombinationBothResponses responseBodyRequestTwo =
                                            completableFuture2.get(); // Not asynchronous
                                    combinationBothResponses.setSuccess(responseBodyRequestTwo.getSuccess());
                                    return combinationBothResponses;

                                } catch (InterruptedException | ExecutionException e) {
                                    e.printStackTrace();
                                }
                            }
                            throw new RuntimeException();
                        });
    }

    private CompletableFuture<CombinationBothResponses> sendSecondPostRequest(
            int valueToBeUsedInRequestBody2) {
        RequestBodyTwo requestBodyTwo = new RequestBodyTwo(valueToBeUsedInRequestBody2, "request 2");
        HttpRequest httpRequest =
                HttpRequest.newBuilder(URI.create("https://reqbin.com/echo/post/json"))
                        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .POST(HttpRequest.BodyPublishers.ofString(jsonb.toJson(requestBodyTwo)))
                        .build();

        return httpClient
                .sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
                .thenApply(
                        httpResponse -> {
                            if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
                                CombinationBothResponses responseBodyRequestTwo =
                                        jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
                                return responseBodyRequestTwo;
                            }
                            throw new RuntimeException();
                        });
    }
}
@Data
@NoArgsConstructor
public class RequestBodyOne {
    private int userId;
    private int id;
    private String title;
    private String body;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RequestBodyTwo {
    private int id;
    private String key;
}
@Data
@NoArgsConstructor
public class CombinationBothResponses {
    private int userId;
    private int id;
    private String title;
    private String body;

    private String success;

}

Response to request 1:

{ "userId": 0, "id": 101, "title": "3", "body": "4" }

Response to request 2:

{"success":"true"}

Combined responses; response of REST controller:

{
"userId": 0,
"id": 101,
"title": "3",
"body": "4",
"success": "true" }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稚气少女 2025-02-09 02:58:23
return httpClient
     .sendAsync(httpRequestOne, HttpResponse.BodyHandlers.ofString())
     .thenCompose(httpResponse -> {
         if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
             final CombinationBothResponses combinationBothResponses = jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
             // 2. Use one value from response 1 for request 2
             int valueToBeUsedInRequestBody2 = combinationBothResponses.getId();
             // 3. Send POST request 2
             return sendSecondPostRequest(valueToBeUsedInRequestBody2)
                 .thenApply(responseBodyRequestTwo -> {
                     // 4. Combine response 1 and response 2 to the final response of REST controller
                     combinationBothResponses.setSuccess(responseBodyRequestTwo.getSuccess());
                     return combinationBothResponses;
                 });
         }
         return CompletableFuture.failedFuture(new RuntimeException());
     });
return httpClient
     .sendAsync(httpRequestOne, HttpResponse.BodyHandlers.ofString())
     .thenCompose(httpResponse -> {
         if (HttpStatus.valueOf(httpResponse.statusCode()).is2xxSuccessful()) {
             final CombinationBothResponses combinationBothResponses = jsonb.fromJson(httpResponse.body(), CombinationBothResponses.class);
             // 2. Use one value from response 1 for request 2
             int valueToBeUsedInRequestBody2 = combinationBothResponses.getId();
             // 3. Send POST request 2
             return sendSecondPostRequest(valueToBeUsedInRequestBody2)
                 .thenApply(responseBodyRequestTwo -> {
                     // 4. Combine response 1 and response 2 to the final response of REST controller
                     combinationBothResponses.setSuccess(responseBodyRequestTwo.getSuccess());
                     return combinationBothResponses;
                 });
         }
         return CompletableFuture.failedFuture(new RuntimeException());
     });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文