将 Play 框架中的 WebSockets 从 2.4 版转换为 2.6 版

Posted

技术标签:

【中文标题】将 Play 框架中的 WebSockets 从 2.4 版转换为 2.6 版【英文标题】:Converting WebSockets in Play framework from version 2.4 to 2.6 【发布时间】:2017-09-17 17:18:29 【问题描述】:

我正在尝试将这段使用 Play 版本 2.4 的代码转换为当前版本 (2.6),但我遇到了一些问题,因为我仍然是 Scala 的菜鸟。

def wsWeatherIntervals = WebSocket.using[String] 
  request =>
    val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
    val outEnumerator = Enumerator.repeatM[String](
      Thread.sleep(3000)
      ws.url(url).get().map(r => s"$new java.util.Date()\n $r.body")
    )
    (Iteratee.ignore[String], outEnumerator)

我关注了this guide,但现在我被困在应该返回该方法的内容上。 这是我尝试使用 2.6 版运行的代码:

  import play.api.mvc._
  import scala.concurrent.Future
  import akka.stream.scaladsl._
  def wsWeatherIntervals = WebSocket.accept[String, Future[String]]  res =>
    val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
    val source = Source.repeat(
      Thread.sleep(3000)
      ws.url(url).get().map(r => s"$new java.util.Date()\n $r.body")
    )
    Flow.fromSinkAndSource(Sink.ignore, source)
  

但是我在运行服务器时遇到了这个错误,它指向方法的第一行:

could not find implicit value for parameter transformer: play.api.mvc.WebSocket.MessageFlowTransformer[String,scala.concurrent.Future[String]]

注意:我也尝试调用WebSocket.apply 而不是WebSocket.accept,并且我搜索了两者之间的差异,但没有找到任何有用的信息。有人可以解释两者之间的区别吗?谢谢。

【问题讨论】:

【参考方案1】:

表面错误是 Play 不知道如何将 Future[String] 转换为 Websocket 消息,您通常会为此使用隐式转换器。但是,在这种情况下,您无论如何都不想返回Future[String],而只是返回一个可以自动编组的普通字符串(使用提供的stringMessageFlowTransformer,因为它发生了。)以下是应该工作的东西:

def wsWeatherIntervals = WebSocket.accept[String, String]  res =>
  val url = "http://api.openweathermap.org/data/2.5/weather?q=Amsterdam,nl"
  def f = ws.url(url).get().map(r => s"$new java.util.Date()\n $r.body")

  val source = Source.unfoldAsync(f)(last => 
    Thread.sleep(3000)
    f.map(next => Some((last, next)))
  )
  Flow.fromSinkAndSource(Sink.ignore, source)

unfoldAsync 源允许我们重复运行一个函数,返回流中下一个元素的未来。 (因为我们希望流永远持续下去,所以我们返回包装为 Some 的值。)

Websocket.apply 方法基本上是accept 的更复杂版本,它允许您通过返回响应以某种原因拒绝 websocket 连接,但如果您需要这样做,最好使用acceptOrResult,它处理将您的流程发出的任何内容转换为 websocket 消息。

【讨论】:

以上是关于将 Play 框架中的 WebSockets 从 2.4 版转换为 2.6 版的主要内容,如果未能解决你的问题,请参考以下文章

Play 框架作为游戏服务器

播放框架用java中的actor处理websockets

使用 Akka 和 Websockets 玩框架

如何将视频从 Play 2 框架流式传输到 HTML5 播放器

如何将参数传递给 Play 中的 Jobs!框架 1.2.x?

播放 WebSockets 服务器推送示例