我对App Engine比较陌生。我不明白如何使用Java异步发出HTTP请求。我原以为使用Thread和Runnable这是一个非常简单的事情。但似乎App Engine不允许使用它们。
public Hashtable someApiMethod(..) {
SomeEntity entity = new SomeEntity(..);
ObjectifyService.ofy().save().entity(entity).now();
makeSomeHttpRequest(entity);
return launchResponse;
}
我的问题是:如何实现makeSomeHttpRequest(..)方法,使其返回而不等待URLFetchService.fetchAsync返回。我没有成功尝试以下内容:
protected void makeSomeHttpRequest(SomeEntity entity) {
URLFetchService fetcher = URLFetchServiceFactory.getURLFetchService();
try {
URL url = new URL("https://www.example.com");
Future future = fetcher.fetchAsync(url);
HTTPResponse response = (HTTPResponse) future.get();
byte[] content = response.getContent();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(content);
String responseString = new String(bos.toByteArray());
int responseCode = response.getResponseCode();
// Here I will do something with the responseCode and responseString
if (responseCode == 200) entity.someValue = responseString;
} catch (IOException e) {
// handle this
} catch (InterruptedException e) {
// handle this
} catch (ExecutionException e) {
// handle this
}
}
我真正要做的是执行此HTTP请求,而不强制someApiMethod方法等待响应。
答案 0 :(得分:0)
少数事情:
首先。 Future
不会以这种方式工作。方法.get
等待功能执行的结果,所以基本上你要停止当前线程,直到其他线程完成其执行。你让它同步,它没有任何意义。通常在稍后调用.get
时,当前线程中的所有其他工作都已完成
二。 Appengine中的线程仅限于当前请求,您必须在当前请求期间完成所有异步处理。因此,以这种方式更新实体并没有多大意义,它仍然受当前请求的约束。我的意思是在您的情况下makeSomeHttpRequest(entity);
应该比return launchResponse;
您真正需要的是将此数据发送到 TaskQueue 并从那里处理SomeEntity entity
(但不要发送实体本身,只需发送ID并按ID加载从队列任务)。基本上它将成为一个新的请求处理程序(servlet / controller / etc),它应该通过id加载实体,执行makeSomeHttpRequest
(同步)并返回http状态200.
请参阅TaskQueue文档:https://cloud.google.com/appengine/docs/java/taskqueue/
您最有可能需要推送队列:https://cloud.google.com/appengine/docs/java/taskqueue/overview-push