英文:
Synchronize the asynchronous callback method call
问题
我们正在开发一个类似这样的解决方案;
请求:(我们通过 API 调用接收请求,并通过我们使用的库发送到第三方)
我们的客户端 --> 我们的 API --> 第三方
响应:(这个响应是我们通过我们正在使用的库中提供的回调方法异步从第三方接收的)
第三方 --> 我们的代码 --> 我们的客户端
以下是相关代码,并且希望摆脱 Thread.sleep() 的调用,改用回调来提供响应。
----- API 方法 -------------
@GetMapping
public ResponseEntity<String> getData(@RequestBody String requestId) throws SessionNotFound, InterruptedException {
dataService.get(requestId);
String msg;
long start = System.currentTimeMillis();
do {
// 我们希望摆脱这个 sleep() 语句,并以某种方式在此处进行回调,一旦有消息就立即回调。
Thread.sleep(30);
msg = clientApp.getRespnse(requestId);
} while(msg == null);
return ResponseEntity.ok(msg);
}
------- Service 类和方法 ---------------
@Service
public class DataService {
@Autowired
private ClientApp clientApp;
public void get(String requestId) throws SessionNotFound {
// 这个方法来自我们使用的库。它只提交请求,响应在不同的方法中接收。
send(requestId);
}
------- Component 类和方法 ---------------
@Component
public class ClientFixApp {
private Map<String, String> responseMap = new HashMap<>();
// 这个方法是来自第三方库的回调,每当有响应时,这个方法将被调用,我们需要将这个消息作为 API 调用的响应发送出去。
@Override
public void onResponse(String requestId)
throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
responseMap.put(msgId, jsonMsg);
}
public String getRespnse(String requestId) {
return responseMap.get(requestId);
}
}
英文:
We are working on a solution which is like this;
Request: (We receive the request via API call and send to third-party via a library we use)
OUR-Client --> OUR-API --> THIRD-PARTY
Response: (This response we receive from third-party asynchronously through a callback method given in the library we are using)
THIRD-PARTY --> OUR-CODE --> OUR-Client
Here is the below code and want to get rid of Thread.sleep() call and make use of the callback to provide response.
----- API Method -------------
@GetMapping
public ResponseEntity<String> getData(@RequestBody String requestId) throws SessionNotFound, InterruptedException {
dataService.get(requestId);
String msg;
long start = System.currentTimeMillis();
do {
// We want to get rid of this sleep() statement and some way to callback here as soon there is message.
Thread.sleep(30);
msg = clientApp.getRespnse(requestId);
} while(msg == null);
return ResponseEntity.ok(msg);
}
------- Service Class and Methods ---------------
@Service
public class DataService {
@Autowired
private ClientApp clientApp;
public void get(String requestId) throws SessionNotFound {
// This method is from the library we use. This only submits the request, response is received on different method.
send(requestId);
}
------- Component Class and Methods ---------------
@Component
public class ClientFixApp {
private Map<String, String> responseMap = new HashMap<>();
// This method is callback from the third party library, whenever there is response this method will get invoked and this message we need to send as response of the API call.
@Override
public void onResponse(String requestId)
throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
responseMap.put(msgId, jsonMsg);
}
public String getRespnse(String requestId) {
return responseMap.get(requestId);
}
}
答案1
得分: 1
DataService
和ClientFixApp
的设计存在缺陷(事实上,它们是两个不同的类,而应该只有一个,这已经说明了很多问题)。真正的异步程序必须允许注册用户过程作为回调,在I/O操作完成时调用(无论是成功还是失败)。ClientFixApp
在不引起客户端其他选项(除了轮询)的情况下,悄然将结果写入表中。
英文:
DataService
and ClientFixApp
are flawed by design (the very fact it is 2 different classes while there must be one, speaks a lot). Truly asynchronous programs must allow to register user procedure as a callack, called when the I/O operation finished (successfully or not). ClientFixApp
silently writes the result in a table, leaving for client no other option except polling.
答案2
得分: 0
你可以使用任何现有的异步 HTTP 库。例如,下面是在 Java 11 及更高版本中包含的 java.net.http
库的代码示例。其他库具有类似的功能。
public static CompletableFuture<HttpResponse<String>> doGet(String uri) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(uri))
.build();
return client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
}
public static void main(String[] args) {
CompletableFuture<HttpResponse<String>> future = doGet("https://postman-echo.com/get");
future.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
}
英文:
You can use any existing asynchronous http library. For example, below is the code for the library java.net.http
included in Java 11 and later. Other libraries have similar functionality.
public static CompletableFuture<HttpResponse<String>> doGet(String uri) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(uri))
.build();
return client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
}
public static void main(String[] args) {
CompletableFuture<HttpResponse<String>> future = doGet("https://postman-echo.com/get");
future.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论