完整future:如何将两个异步请求组合到一个响应中
第一个请求是异步发送的,然后从对第一个请求的响应中获取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:
- Send POST request 1
- Use the id value from response 1 for request 2
- Send POST request 2
- 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)