【问题标题】:java nested http call api libraryjava嵌套http调用api库
【发布时间】:2014-08-09 09:28:01
【问题描述】:

我正在阅读一些来自 playframework 的 http webservice api,链接如下。

我无法理解这种嵌套如何与平面地图一起使用。

谁能给我一些提示如何破解这个大块的函数调用。

来自http://www.playframework.com/documentation/2.2.x/JavaWS

撰写结果 如果您想按顺序拨打多个电话,
这可以使用 flatMap 来实现:

public static Promise<Result> index() {
    final Promise<Result> resultPromise = WS.url(feedUrl).get().flatMap(
           new Function<WS.Response, Promise<Result>>() {
                public Promise<Result> apply(WS.Response response) {
                    return WS.url(response.asJson().findPath("commentsUrl").asText()).get().map(
                        new Function<WS.Response, Result>() {
                            public Result apply(WS.Response response) {
                                return ok("Number of comments: " + response.asJson().findPath("count").asInt());
                            }
                        }
                );
            }
        }
);
    return resultPromise;
}

【问题讨论】:

    标签: java web-services api web playframework


    【解决方案1】:

    flatMapmap 是常见的 Scala(或更一般地,函数式编程)函数。它们都接受 function 作为参数。为了将 Play WS API 翻译成 Java(以及几乎所有其他内容),Scala 的函数类型需要在 Java 中重新实现,以便您可以充分利用 WS 库。它在这里以与 Scala 编译器类似的方式完成。 Function&lt;A,B&gt; 是一种抽象类型,需要 apply 方法。 apply的参数是函数的参数,apply的返回类型是函数的类型。

    如果你在 Java 中有这个功能:

    public String int2String(Integer integer) {
        return integer.toString();
    }
    

    相当于这样:

    new Function<Integer, String>() {
        public String apply(Integer integer) {
            return integer.toString();
        }
    }
    

    让我们从只有一个 WS 调用的情况开始。 WS.url(...).get() 返回 Promise&lt;WS.Response&gt;Promisepromised 值的容器类。为了处理它包含(或最终将包含)的值,我们需要使用map 函数。对于Promise&lt;WS.Response&gt;map 将接受Function&lt;WS.Response, T&gt; 作为参数,其中T 是您要将响应映射到的类型。

    例如,让我们定义一个 Function,它只会在 Play HTTP Result 中返回 WS.Response 的正文:

    Function<WS.Response, Result> echo = new Function<WS.Response, Result>() {
        public Result apply(WS.Response response) {
            return ok(response.asText());
        }
    }
    

    现在让我们在控制器的 WS 调用中使用这个 Function

    public static Promise<Result> index() {
    
        final Promise<Result> resultPromise = WS.url("http://google.com").get().map(echo);
    
        return resultPromise;
    
    }
    

    一旦满足Promise,前面定义的echo函数将在map内部执行,返回Promise&lt;Result&gt;。前面两段代码也可以这样写(与匿名函数合二为一):

    public static Promise<Result> index() {
    
        final Promise<Result> resultPromise = WS.url("http://google.com").get().map(
            new Function<WS.Response, Result>() {
                public Result apply(WS.Response response) {
                    return ok(response.asText());
                }
            }
        );
    
        return resultPromise;
    }
    

    作为一个粗略的例子,假设我们需要进行两次 WS 调用。第二个 WS 调用将取决于第一个。也许第一次调用会给我们一些 URL,我们将使用它来进行第二次 WS 调用。

    这就是flatMap 出现的地方。我们需要两个函数来完成这个任务。第一个函数是传递给flatMap 的函数,它将在收到第一个WS.Response 时执行。第一个函数将使用第一个响应来进行第二个 WS 调用,该调用返回另一个 Promise&lt;WS.Response&gt;,必须映射它才能获得最终结果。所以我们 map 使用第二个函数将第二个结果转换为 WS.Response 到我们的 Result

    那么发生了什么?如果我们在这两种情况下都使用map 而不是flatMap,则事件链将如下所示:

    第一个get()返回一个Promise&lt;WS.Response&gt;,然后我们将map包含的WS.Response返回一个Promise&lt;Result&gt;。然而,这会给我们留下一个Promise&lt;Promise&lt;WS.Response&gt;&gt;,这不是很理想。在外部函数中使用flatMap 会将Promises 扁平化为单个Promise&lt;Result&gt;。同样,如果您进行 3 次或更多嵌套调用,您会将每个结果 map 传递给一个内部函数,并且在外部级别只有一个 flatMap 以在最后展平所有内容。

    这一切在 Scala 中当然看起来更漂亮。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 2016-01-27
      • 1970-01-01
      相关资源
      最近更新 更多