我正在使用的应用程序将按以下顺序使用2个REST web服务:
1) 计数记录-了解特定时间范围内的记录数。
2)获取记录——一旦我们有了记录的数量,我们就需要调用这项服务。但是这项服务有一个门槛来一次性获取10K记录。假设第一个服务在特定的时间间隔内告诉我,它有100K的记录,那么我需要以分页方式调用第二个网络服务10次,考虑到它的阈值是一次10K的。
因此,如果我将进行10次同步调用,我的应用程序将太慢而无法响应。所以我需要一种机制来进行异步调用。
我在后端代码中使用spring框架,在web服务调用中使用rest模板。我希望找到对上述PostWeb服务进行异步调用的最佳方法
我做了一些研究,发现异步方法如下:https://spring.io/guides/gs/async-method/
您能告诉我这是我所看到的一种正确的方法吗?或者这是一种更好的异步调用方法吗?期待您的建议,谢谢!
如果它真的必须是异步的,那么使用Spring实现似乎是一个明智的想法。
这只是对@shawn答案的改进。在前面提供的实现中,有时我会遇到以下问题:
while (responses < futures.size()) {
for (Future<ResponseEntity<List<Record>>> future : futures) {
if (future.isDone()) {
responses++;
try {
ResponseEntity<List<Record>> responseEntity = future.get();
fullListOfRecords.addAll(responseEntity.getBody());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
在这里,如果处理了6个线程,有时同一个线程被允许在上面的块中多次输入,所以它最终会有重复的记录作为响应。所以为了避免这种情况,我添加了回调块来创建最终响应,确保没有重复的响应,尽管我们仍然需要while(响应)
@Component
public class SampleAsyncService {
private RestTemplate restTemplate;
private AsyncRestTemplate asyncRestTemplate;
@Value("${myapp.batchSize:1000}")
private int batchSize;
public SampleAsyncService(AsyncRestTemplate asyncRestTemplate, RestTemplate restTemplate) {
this.asyncRestTemplate = asyncRestTemplate;
this.restTemplate = restTemplate;
}
public List<Record> callForRecords() {
ResponseEntity<Integer> response = restTemplate.getForEntity("http://localhost:8081/countService",
Integer.class);
int totalRecords = response.getBody().intValue();
List<Future<ResponseEntity<List<Record>>>> futures = new ArrayList<Future<ResponseEntity<List<Record>>>>();
for (int offset = 0; offset < totalRecords;) {
ListenableFuture<ResponseEntity<List<Record>>> future = asyncRestTemplate.exchange(
"http://localhost:8081/records?startRow={}&endRow={}", HttpMethod.GET, null,
new ParameterizedTypeReference<List<Record>>() {
}, offset, batchSize);
future.addCallback(
new ListenableFutureCallback<ResponseEntity<ChatTranscript>>() {
@Override
public void onSuccess(ResponseEntity<ChatTranscript> response) {
fullListOfRecords.addAll(responseEntity.getBody());
log.debug("Success: " + Thread.currentThread());
}
@Override
public void onFailure(Throwable t) {
log.debug("Error: " + Thread.currentThread());
}
}
);
futures.add(future);
offset = offset + batchSize;
}
int responses = 0;
List<Record> fullListOfRecords = new ArrayList<Record>();
while (responses < futures.size()) {
for (Future<ResponseEntity<List<Record>>> future : futures) {
if (future.isDone()) {
responses++;
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
return fullListOfRecords;
}
public class Record {
}
}
@Journycorner linked是一个很好的开始,但它并没有真正展示整个画面,因为它只发出一个请求。使用Future
无疑是正确的。Spring4提供了一个AsyncRestTemplate
,它返回一个Future
,这正是您想要使用的。
在我的手机上,所以无法写出完整的代码,但这大致就是你想要做的。
@Component
public class SampleAsyncService {
private RestTemplate restTemplate;
private AsyncRestTemplate asyncRestTemplate;
@Value("${myapp.batchSize:1000}")
private int batchSize;
public SampleAsyncService(AsyncRestTemplate asyncRestTemplate, RestTemplate restTemplate) {
this.asyncRestTemplate = asyncRestTemplate;
this.restTemplate = restTemplate;
}
public List<Record> callForRecords() {
ResponseEntity<Integer> response = restTemplate.getForEntity("http://localhost:8081/countService",
Integer.class);
int totalRecords = response.getBody().intValue();
List<Future<ResponseEntity<List<Record>>>> futures = new ArrayList<Future<ResponseEntity<List<Record>>>>();
for (int offset = 0; offset < totalRecords;) {
ListenableFuture<ResponseEntity<List<Record>>> future = asyncRestTemplate.exchange(
"http://localhost:8081/records?startRow={}&endRow={}", HttpMethod.GET, null,
new ParameterizedTypeReference<List<Record>>() {
}, offset, batchSize);
futures.add(future);
offset = offset + batchSize;
}
int responses = 0;
List<Record> fullListOfRecords = new ArrayList<Record>();
while (responses < futures.size()) {
for (Future<ResponseEntity<List<Record>>> future : futures) {
if (future.isDone()) {
responses++;
try {
ResponseEntity<List<Record>> responseEntity = future.get();
fullListOfRecords.addAll(responseEntity.getBody());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
return fullListOfRecords;
}
public class Record {
}
}
*更新*创建完整的代码示例。
我是web服务开发的初学者。我们正在使用Spring3用java构建RESTWeb应用程序。 我们正在使用的Web服务具有异步登录方法。我们为他们提供了一个回调监听器URL,他们的服务在其中发回响应。 因此,当我们发送登录请求时,我们会收到一个空白响应作为确认。和服务发送一个响应,其中包含侦听器URL上的实际数据。 请帮助,我应该如何设计/实现调用登录服务作为同步调用?谢谢 编辑:下面是回发消息的
我在Scala上使用Play 2.5,我创建了一个类,可以多次调用外部web服务。 外部Web服务在某些条件下被调用并得到ok或nok的简单响应。如果可以,那么我应该更新内部对象状态,如果可以,我现在什么也不做。 这是我的类,它将String的列表作为参数,并返回要在控制器中处理的对象的Future列表。 是列表类型的列表,但我希望它只是一个简单的响应列表。 1)如何简化和纠正我的代码以获得响应列
在我的项目中,有一个返回类型为未来列表的方法。另一个开发人员也这样迭代过for循环 现在,我必须在处理列表的对象后立即对它执行某些操作。我该怎么做?即使我把一个for循环像 如果第一个对象未被处理,isDone()条件将失败,它将被忽略,第二次迭代将开始,我如何处理它? 这也可以使用ExecutorService完成吗??我不熟悉ExecutorService。 编辑:所以我编辑了服务类的方法2(
问题内容: 我有两个从jquery到Web服务的ajax调用。 第一次调用()在javascript ()中开始一个间隔,并返回存储在会话变量中的消息的字符串数组。 第二个调用()上传用户并将状态保存在要返回的会话中。因此,UploadUsers将消息添加到Session,而GetMessages检索消息并将其显示给客户端。 问题是即使我异步调用这两个方法,也要等到完成。它只是加载。 我什至在要添
同步调用异步方法最安全的方法是什么?
我喜欢新的System.net.Http.HttpClient类。它有一个很好的简单的API,它不会抛出正常的错误。但它只是异步的。 我需要代码(深入服务器内部) 编辑:我让PM女士最近向我确认,有一个命令“任何可能采取>X MS(我忘了X)的API必须是异步的”,许多PMs将此解释为“只有异步”(不清楚这是否是意图)。因此,文档DB api只是异步的。