无法找到ActorSystem的隐含值

时间:2018-03-16 00:42:43

标签: scala akka akka-stream akka-http

我刚刚开始使用Akka和Scala,我尝试使用Akka Streams连接到WebSocket。我在下面创建了我的SocketActor,并尝试从main方法实例化。

这是我的package com.lightbend.akka.sample import akka.actor.{Actor, Props} import akka.Done import akka.http.scaladsl.Http import akka.stream.scaladsl._ import akka.http.scaladsl.model.ws._ import scala.concurrent.Future object SocketActor { def props(coinApiIdentifier: String): Props = Props(new SocketActor(coinApiIdentifier)) case object Start case object Stop } class SocketActor(val ticker: String) extends Actor { import SocketActor._ // Future[Done] is the materialized value of Sink.foreach, // emitted when the stream completes private val incoming: Sink[Message, Future[Done]] = Sink.foreach[Message] { case message: TextMessage.Strict => println(message.text) } // send this as a message over the WebSocket private val outgoing = Source.single(TextMessage("hello world!")) // flow to use (note: not re-usable!) private val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("wss://api.com/v1/")) // the materialized value is a tuple with // upgradeResponse is a Future[WebSocketUpgradeResponse] that // completes or fails when the connection succeeds or fails // and closed is a Future[Done] with the stream completion from the incoming sink private val graph = outgoing .viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse] .toMat(incoming)(Keep.both) // also keep the Future[Done] override def receive: PartialFunction[Any, Unit] = { case Start => println("Start message received.") graph.run() } }

object AkkaQuickstart extends App {

  // Create the 'helloAkka' actor system
  val system: ActorSystem = ActorSystem("test")
  val materializer: ActorMaterializer = ActorMaterializer()

  val socketActor: ActorRef =
    system.actorOf(SocketActor.props("hello"), "socket-actor")

  socketActor ! Start
}

我的主要方法:

implicit

不幸的是,我收到错误:

  

错误:(38,35)找不到参数系统的隐含值:   akka.actor.ActorSystem private val webSocketFlow =   HTTP().webSocketClientFlow(WebSocketRequest(" WSS://api.com/v1/"))

我已经尝试将一些SocketActor参数传递给ActorSystem的构造函数,但这样做效果不佳。似乎system由于某种原因不在范围内。如何在Http()中获取SocketActor功能的{{1}}范围?

1 个答案:

答案 0 :(得分:4)

定义隐式val

class SocketActor(val ticker: String) extends Actor {
  implicit val sys = context.system
  // ...
}

这将提供ActorSystem对象所期望的隐式Http

您的代码还有另一个问题:您的actor中的流将无法运行,因为范围中没有物化器。解决这个问题的一种方法是在actor中创建一个物质化器:

class SocketActor(val ticker: String) extends Actor {
  implicit val sys = context.system
  implicit val mat = ActorMaterializer()(context)
  // ...
}

请注意,如果将投影仪定义为implicit val mat = ActorMaterializer(),则由于context.system,它会隐式使用implicit val sys = context.system。相反,使用actor context显式创建了Materializer。这是因为documentation

中的警告
  

不要通过将context.system传递给actor来在actor中创建新的actor实现器。这将导致为每个这样的actor创建一个新的ActorMaterializer并可能泄露(除非你明确地将其关闭)。相反,建议传入Materializer或使用actor的context创建一个。

推荐的方法允许actor的创建者重用一个物化器,它将物化器作为隐式参数传递给actor:

class SocketActor(val ticker: String)(implicit val mat: ActorMaterializer) extends Actor {
  implicit val sys = context.system
  // ...
}

然后你可以将主程序中的物化器传递给这个actor:

object AkkaQuickstart extends App {

  implicit val system: ActorSystem = ActorSystem("test")
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  val socketActor: ActorRef =
    system.actorOf(Props(classOf[SocketActor], "hello", materializer), "socket-actor")

  socketActor ! Start
}