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

我想要做的基本上是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是一个密封的特性,可能有充分的理由……

最佳答案 定义MessageFlowTransformer [[String,Array [Byte]],[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)
      })
    }
  }
}
点赞