我有一个模型,我想用来自 Web 服务的详细信息来填充它。我想异步执行此操作,以免阻塞服务器线程。让我们假设它是一个登录服务。
现在我想做的是向远程服务器发出请求并最终返回一个用户模型对象。所以方法签名看起来像这样:
public static User loginUser(String username, String password) {
我知道要对 Web 服务进行异步调用,我应该使用Promise
:
Promise<WS.Response> wsPromise = WS.url("http://myserver.com/login")
.setContentType("application/json; charset=utf-8")
.post("... the username and password ...");
哪个还没有开始请求。我可以调用get()
这个对象来对服务进行阻塞调用。这行得通。
要异步执行此操作,我认为我需要映射它并以某种方式执行它。
Promise<User> resultPromise = wsPromise.map(new F.Function<WS.Response, User>() {
@Override
public User apply(WS.Response response) throws Throwable {
System.out.println(response.getBody());
return new User(... based on something extracted from the returned JSON ...);
}
});
现在如何触发此操作?如果我调用get()
,resultPromise
它会进行调用,但最终会触发超时异常。我不能使用该async(...)
方法,因为它只返回我一个Result
.
查看其他示例(https://github.com/jroper/play-promise-presentation/blob/master/src/main/java/controllers/Application.java),这似乎是模式。即我们总是希望返回一个 Result 对象。但是,我无法查询Result
对象,也没有计划将该特定对象发送给用户。
事实上,这些示例似乎调用了一个 Web 服务,将 JSON 结果映射到一个对象,然后立即将它们映射回相同的 JSON。当我想将用户(在我的情况下)传递回调用函数时没有多大用处。
老实说,无论如何,我对这种异步性质有点困惑(你可能已经猜到了)。特别是,这实际上是一个阻塞操作,因为我们必须等待 Web 服务返回响应。该文档似乎表明使用Promise
/Future
模式将避免这种阻塞。
底线是:如何在不阻塞 Play Framework 服务器中的线程的情况下将 Web 服务调用的结果映射回模型对象?
随意滥用我对 Play Framework 的缺乏经验......