web-services - 从 play 2 调用多个 Web 服务

标签 web-services scala playframework-2.0

我是 play2.0-Scala 初学者,必须调用多个 Web 服务来生成 HTML 页面。

阅读 The Play WS API 后页面和非常有趣的article from Sadek Drobi我仍然不确定实现此目标的最佳方法是什么。

本文展示了一些代码片段,作为 Play 初学者,我无法完全理解这些代码片段。

第 4 页上的图 2:

val response: Either[Response,Response] =
  WS.url("http://someservice.com/post/123/comments").focusOnOk

val responseOrUndesired: Either[Result,Response] = response.left.map {
  case Status(4,0,4) => NotFound
  case Status(4,0,3) => NotAuthorized
  case _ => InternalServerError
}

val comments: Either[Result,List[Comment]] = 
responseOrUndesired.right.map(r => r.json.as[List[Comment]])

// in the controller
comment.fold(identity, cs => Ok(html.showComments(cs)))

最后一行 fold 的作用是什么? comment 应该是comments 吗?我没有将最后一条语句分组到 Async block 中吗?

图 4 显示了如何将多个 IO 调用与单个 for 表达式组合起来:

for {
  profile <- profilePromise
  events <- attachedEventsPromise
  articles <- topArticlesPromise
} yield Json.obj(
  "profile" -> profile,
  "events" -> events,
  "articles" -> articles )

}

// in the controller
def showInfo(...) = Action { rq =>
  Async {
    actorInfo(...).map(info => Ok(info))
  }
}

我如何使用这个片段? (我对 for 表达式后面的额外的 -} 感到有点困惑。) 我应该写这样的东西吗?

var actorInfo = for {                // Model
  profile <- profilePromise
  events <- attachedEventsPromise
  articles <- topArticlesPromise
} yield Json.obj(
  "profile" -> profile,
  "events" -> events,
  "articles" -> articles )

def showInfo = Action { rq =>         // Controller
  Async {
    actorInfo.map(info => Ok(info))
  }
}

组合图 2 和图 4 中的片段的最佳方法是什么(错误处理 + IO 非阻塞调用的组合)? (例如,如果任何被调用的 Web 服务产生错误 404,我希望产生错误 404 状态代码)。

也许有人知道在 play 框架中调用 Web 服务的完整示例(在 play 示例应用程序或其他任何地方找不到示例)。

最佳答案

我不得不说,这篇文章在图 2 中显示的示例中是错误的。Play 2.0 中不存在 focusOnOk 方法。我假设这篇文章的作者当时使用的是 Play 2 的预发行版本。

关于评论,是的,应该是评论。语句中的 fold 正在对 Either 进行操作。它需要 2 个函数作为参数。第一个是左值时要应用的函数。第二个是如果它是正确值则应用的函数。更详细的解释可以在这里找到:http://daily-scala.blogspot.com/2009/11/either.html

所以这条线的作用是。如果我有左值(这意味着我得到了不需要的响应),请应用内置的 Identity 函数,它只会返回该值。如果它具有正确的值(这意味着我得到了 OK 响应),请创建一个以某种方式显示评论的新结果。

关于Async,它实际上并不是异步的。 focusOnOk 是一个阻塞函数(Play 1.x 的旧 Java 时代的残余)。但请记住,这不是有效的 Play 2 代码。

对于图 4,尾随的 } 实际上是因为它是图 3 中内容的部分替代。而不是众多的 promise flatMap。你可以做for comprehension反而。另外,我认为它应该是 userInfo(...).map 而不是 actorInfo(...).map

Play documentation您链接到的实际上已经向您展示了一个完整的示例。

def feedTitle(feedUrl: String) = Action {
  Async {
    WS.url(feedUrl).get().map { response =>
      Ok("Feed title: " + (response.json \ "title").as[String])
    }
  }  
}

将获取 feedUrl 中的任何内容,然后将其映射以对 response 执行某些操作,该响应具有可以检查的 status 字段看看是 404 还是其他什么。

为此,链接文章的图 3 和图 4 应该为您提供一个起点。所以你会得到类似的东西,

def getInfo(...) : Promise[String] = {
  val profilePromise = WS.url(...).get()
  val attachedEventsPromise = WS.url(...).get()
  val topArticlesPromise = WS.url(...).get()

  for {
    profile <- profilePromise
    events <- attachedEventsPromise
    articles <- topArticlesPromise
  } yield {
    // or return whatever you want
    // remember to change String to something else in the return type
    profile.name 
  }
}

def showInfo(...) = Action { rq =>
  Async { 
    getInfo(...).map { info =>
      // convert your info to a Result
      Ok(info)
    }
  }
}

关于web-services - 从 play 2 调用多个 Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12246541/

相关文章:

web-services - htaccess 允许 .txt 文件

jakarta-ee - 使用 JPA Play Framework : Solution for storing a Map, 键值

json - 如何在 play framework 2.0 上将 scala 中的 mutableList 解析为 JSON?

java - 什么基于 JVM 的脚本语言支持@WebService 在运行时创建服务?

c# - 从代理服务器后面调用网络服务

scala - 在 Scala 中使用 def 定义字段是什么意思?

scala - 在 Scala 3 中是否可以通过泛型类型进行模式匹配?

mongodb - Mongo Shell 显示已添加文档,但 Scalatest 中断言失败

many-to-many - 如何使用 Ebean 处理单向多对多关系

javascript - Ratchet Websockets - 检测断开连接的客户端