使用 completableFuture 从 doPOST 写入 doGET 响应
Use completableFuture to write doGET response from doPOST
我有 2 个 API(doGET 和 doPOST),我正在尝试使用异步机制使 doPOST 为 doGET 请求写入 httpServletResponse
。
我的控制流程-
- 客户端发出请求A (getData) 调用
- Java 服务器进行一些处理并调用外部环境第 3 方 API
- 第 3 方 API 没有 return 响应但调用我的另一个端点 doPOST
- doPOST 现在需要将 httpServletResponse 对象写入 doGET
- doGET returndoPOST 完成后立即发送此对象。
为了解决这个问题,我发现我可以使用一些异步编程机制,比如 java 中的 CompletableFuture
。但我对如何在我的代码中准确设置这种机制感到困惑。这是我到目前为止所做的 -
doGET
public void doGET(HttpServletRequest request, HttpServletResponse response) {
// some processing
// Call 3rd Party API
CompletableFuture<HttpServletRequest> completableFuture = CompletableFuture.supplyAsync(() -> doPOST());
while (!completableFuture.isDone()) {
System.out.println("CompletableFuture is not finished yet...");
}
HttpServletRequest result = completableFuture.get();
response = result;
}
我一直无法弄清楚如何为此设置 completableFuture。这里需要帮助。
doPOST
public HttpServletResponse doPOST(HttpServletRequest request, HttpServletResponse response) {
// receive 3rd party request
// add data from 3rd party request into a new response object
// add response object into hashmap
}
我怎样才能正确地完成这项工作?
您可能有请求 ID 与对象的映射,作为 class 的 属性 公开了两种方法:
private final Map<String, HttpRequestResponse> requests = new HashMap<>();
... 其中 class HttpRequestResponse
是请求(您在 doGET
上收到)和响应(将由 [=16 提供)的简单包装=]:
class HttpRequestResponse {
private final HttpServletRequest request;
private final CompletableFuture<HttpServletResponse> responseSupplier;
public HttpRequestResponse(HttpServletRequest request, CompletableFuture<HttpServletResponse> responseSupplier) {
this.request = request;
this.responseSupplier = responseSupplier;
}
public void supplyResponse(HttpServletResponse response) {
this.responseSupplier.complete(response); //<-- this will release the .get()
}
//getters
public CompletableFuture<HttpServletResponse> getSupplier() {
return responseSupplier;
}
}
在doGET
收到请求后,您将创建实例并将其放入地图,然后等待结果:
public void doGET(HttpServletRequest request, HttpServletResponse response) {
HttpRequestResponse responseSupplier = new HttpRequestResponse(request, new CompletableFuture<>());
requests.put(yourId, responseSupplier); //add supplier to the map (so that doPOST can retrieve it later)
//perform request to your 3rd party API
response = responseSupplier.getSupplier().get(); //<- wait until someone completes the future
}
另一方面,在 doPOST
收到第 3 方 API 的响应后,您需要通过其 id 获取未来,将其从地图中删除并完成:
public void doPOST(HttpServletRequest request, HttpServletResponse response) {
HttpRequestResponse responseSupplier = requests.remove(yourId); //<-- removes the supplier from the map and returns it to you
responseSupplier.getSupplier().complete(<your response>); //<-- once you complete the future with a result, the .get() which is hanging on doGET will return
}
问题:如果 doGET
在继续之前等待响应准备好,为什么要使用异步模式?
我想一旦你把它放在适当的位置,doGET
也可以变成异步的,return 执行 id(然后客户端可以监听结果)。
我有 2 个 API(doGET 和 doPOST),我正在尝试使用异步机制使 doPOST 为 doGET 请求写入 httpServletResponse
。
我的控制流程-
- 客户端发出请求A (getData) 调用
- Java 服务器进行一些处理并调用外部环境第 3 方 API
- 第 3 方 API 没有 return 响应但调用我的另一个端点 doPOST
- doPOST 现在需要将 httpServletResponse 对象写入 doGET
- doGET returndoPOST 完成后立即发送此对象。
为了解决这个问题,我发现我可以使用一些异步编程机制,比如 java 中的 CompletableFuture
。但我对如何在我的代码中准确设置这种机制感到困惑。这是我到目前为止所做的 -
doGET
public void doGET(HttpServletRequest request, HttpServletResponse response) {
// some processing
// Call 3rd Party API
CompletableFuture<HttpServletRequest> completableFuture = CompletableFuture.supplyAsync(() -> doPOST());
while (!completableFuture.isDone()) {
System.out.println("CompletableFuture is not finished yet...");
}
HttpServletRequest result = completableFuture.get();
response = result;
}
我一直无法弄清楚如何为此设置 completableFuture。这里需要帮助。
doPOST
public HttpServletResponse doPOST(HttpServletRequest request, HttpServletResponse response) {
// receive 3rd party request
// add data from 3rd party request into a new response object
// add response object into hashmap
}
我怎样才能正确地完成这项工作?
您可能有请求 ID 与对象的映射,作为 class 的 属性 公开了两种方法:
private final Map<String, HttpRequestResponse> requests = new HashMap<>();
... 其中 class HttpRequestResponse
是请求(您在 doGET
上收到)和响应(将由 [=16 提供)的简单包装=]:
class HttpRequestResponse {
private final HttpServletRequest request;
private final CompletableFuture<HttpServletResponse> responseSupplier;
public HttpRequestResponse(HttpServletRequest request, CompletableFuture<HttpServletResponse> responseSupplier) {
this.request = request;
this.responseSupplier = responseSupplier;
}
public void supplyResponse(HttpServletResponse response) {
this.responseSupplier.complete(response); //<-- this will release the .get()
}
//getters
public CompletableFuture<HttpServletResponse> getSupplier() {
return responseSupplier;
}
}
在doGET
收到请求后,您将创建实例并将其放入地图,然后等待结果:
public void doGET(HttpServletRequest request, HttpServletResponse response) {
HttpRequestResponse responseSupplier = new HttpRequestResponse(request, new CompletableFuture<>());
requests.put(yourId, responseSupplier); //add supplier to the map (so that doPOST can retrieve it later)
//perform request to your 3rd party API
response = responseSupplier.getSupplier().get(); //<- wait until someone completes the future
}
另一方面,在 doPOST
收到第 3 方 API 的响应后,您需要通过其 id 获取未来,将其从地图中删除并完成:
public void doPOST(HttpServletRequest request, HttpServletResponse response) {
HttpRequestResponse responseSupplier = requests.remove(yourId); //<-- removes the supplier from the map and returns it to you
responseSupplier.getSupplier().complete(<your response>); //<-- once you complete the future with a result, the .get() which is hanging on doGET will return
}
问题:如果 doGET
在继续之前等待响应准备好,为什么要使用异步模式?
我想一旦你把它放在适当的位置,doGET
也可以变成异步的,return 执行 id(然后客户端可以监听结果)。