Play Framework 2 - 调用Web服务并返回一个对象

Ste*_*e N 5 java playframework-2.0

我有一个模型,我想填充Web服务的详细信息.我想异步这样做,以免阻塞服务器线程.我们假装它是一个登录服务.

现在我想要做的是向远程服务器发出请求并最终返回User模型对象.所以方法签名看起来像这样:

public static User loginUser(String username, String password) {
Run Code Online (Sandbox Code Playgroud)

我理解为了对Web服务进行异步调用,我应该使用Promise:

Promise<WS.Response> wsPromise = WS.url("http://myserver.com/login")
            .setContentType("application/json; charset=utf-8")
            .post("... the username and password ...");
Run Code Online (Sandbox Code Playgroud)

哪个还没有启动请求.我可以调用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 ...);
    }
});
Run Code Online (Sandbox Code Playgroud)

现在我该如何触发此操作?如果我打电话get()给它resultPromise,它会拨打电话,但最终会触发超时例外.我不能使用这个async(...)方法,因为那只会给我一个回复Result.

看看其他例子(https://github.com/jroper/play-promise-presentation/blob/master/src/main/java/controllers/Application.java),这似乎是模式.即我们总是希望返回一个Result对象.但是,我无法查询Result对象,我也没有计划将该特定对象发送给用户.

实际上,这些示例似乎调用Web服务,将JSON结果映射到对象,然后立即将它们映射回相同的JSON.当我想将User(在我的情况下)传递回调用函数时,没什么用处.

说实话,我对这种异步性质有点困惑(你可能已经猜到了).特别是,这实际上是一个阻止操作,因为我们必须等待Web服务返回响应.文档似乎表明使用Promise/ Futurepatterns将避免这种阻塞.

底线是:如何在不阻止Play Framework服务器中的线程的情况下将Web服务调用的结果映射回模型对象?

随意滥用我对Play Framework缺乏经验...

小智 2

这个答案可能来得太晚了,但会发布它,以防现在其他人仍然想知道同样的问题并想要问题的答案。

有两种方法可以实现此目的,即使两者都使用相同的JsonNode类:

  1. 第一个是您所期望的:“新用户(..某事...)”

在这种情况下,您可以使用 JsonNode 的“get”方法来获取创建 User 对象所需的特定数据(在我的示例中为用户名和电子邮件,因为您没有指定必填字段)。

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());
        JsonNode json = response.asJson();
        return new User(json.get("username"), json.get("email"));
    }
});
Run Code Online (Sandbox Code Playgroud)
  1. 另一种选择是如果您知道 Web 服务确实返回 User 对象的有效 Json 表示形式。

我个人认为这个选项更容易,并且依赖于Json 类中的 fromJson 方法

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 Json.fromJson(response.asJson(), User.class);
    }
});
Run Code Online (Sandbox Code Playgroud)

我希望这个答案可以帮助人们想知道如何以简单的方式做到这一点。