Scala Play WebSocket - 一个Actor,多种消息类型

时间:2017-05-13 19:23:37

标签: scala playframework websocket

我想要做的基本上是1:1这个:Scala Play Websocket - use one out actor to send both: Array[Byte] and String messages

可悲的是,自2.4以来,API发生了很大变化(我现在在2.6.0-M4上)。

我尝试了什么(由于显而易见的原因无法编译):

WebSocket.accept[WSMessage, WSMessage]
    {
      request =>
        ActorFlow.actorRef
        {
          out => WebSocketActor.props(out)
        }
    }


  sealed trait WSMessage
  case class StringMessage(s: String) extends WSMessage
  case class BinaryMessage(a: Array[Byte]) extends WSMessage
  case class JsonMessage(js: JsValue) extends WSMessage

  object MyMessageFlowTransformer
  {
    implicit val WSMessageFlowTransformer: MessageFlowTransformer[WSMessage, WSMessage] =
    {
      new MessageFlowTransformer[WSMessage, WSMessage]
      {
        def transform(flow: Flow[WSMessage, WSMessage, _]) =
        {
          AkkaStreams.bypassWith[Message, WSMessage, Message](Flow[Message] collect
          {
            case StringMessage(s) => Left(s)
            case BinaryMessage(b) => Left(b)
            case JsonMessage(j) => Left(j)
            case _ => Right(CloseMessage(Some(CloseCodes.Unacceptable)))
          })(flow map WSMessage.apply)
        }
      }
    }
  }
我有点迷茫。 play.api.http.websocket.Message是一个密封的特征,可能是有充分理由的......

1 个答案:

答案 0 :(得分:2)

定义MessageFlowTransformer[Either[String, Array[Byte]], Either[String, Array[Byte]]]

type WSMessage = Either[String, Array[Byte]]

implicit val mixedMessageFlowTransformer: MessageFlowTransformer[WSMessage, WSMessage] = {
  new MessageFlowTransformer[WSMessage, WSMessage] {
    def transform(flow: Flow[WSMessage, WSMessage, _]) = {
      AkkaStreams.bypassWith[Message, WSMessage, Message](Flow[Message].collect {
        case BinaryMessage(data) => Left(Right(data.toArray))
        case TextMessage(text) => Left(Left(text))
      })(flow map {
        case Right(data) => BinaryMessage.apply(ByteString.apply(data))
        case Left(text) => TextMessage.apply(text)
      })
    }
  }
}