Scala spray-client定义了AKKA ActorRefFactory的含义

时间:2013-12-07 16:43:07

标签: scala akka actor spray implicits

我正在尝试使用Scala和spray-client编写一个简单的HTTP客户端。我的客户基于Spray docs上给出的示例。

我的问题是这个例子是创建一个新的隐式 ActorSystem,即

implicit val system = ActorSystem()

但我希望我的客户端可以重用,而不是创建一个新的ActorSystem。

这是我的代码的要点。

trait WebClient {
  def get(url: String)(implicit system: ActorSystem): Future[String]
}

object SprayWebClient extends WebClient {
  val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

  def get(url: String): Future[String] = {
    val r = pipeline (Get("http://some.url/"))
    r.map(_.entity.asString)
  }

}

但是我有两个关于implicits的编译器错误

implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext WebClient.scala ...

not enough arguments for method sendReceive: (implicit refFactory: akka.actor.ActorRefFactory, implicit executionContext: scala.concurrent.ExecutionContext, implicit futureTimeout: akka.util.Timeout)spray.http.HttpRequest => scala.concurrent.Future[spray.http.HttpResponse]. Unspecified value parameters refFactory, executionContext.   WebClient.scala...

我应该如何更改API定义?

1 个答案:

答案 0 :(得分:10)

这是一个解决方案:

import akka.actor.ActorSystem
import spray.http.{HttpRequest, HttpResponse}
import scala.concurrent.Future
import spray.client.pipelining._

trait WebClient {
  def get(url: String): Future[String]
}

class SprayWebClient(implicit system: ActorSystem) extends WebClient {
  import system.dispatcher

  val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

  def get(url: String): Future[String] = {
    val r = pipeline (Get("http://some.url/"))
    r.map(_.entity.asString)
  }
}

这是保留原始WebClient.get签名的另一个:

import akka.actor.ActorSystem
import spray.http.{HttpRequest, HttpResponse}
import scala.concurrent.Future
import spray.client.pipelining._

trait WebClient {
  def get(url: String)(implicit system: ActorSystem): Future[String]
}

object SprayWebClient extends WebClient {
  def get(url: String)(implicit system: ActorSystem): Future[String] = {
    import system.dispatcher

    val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
    val r = pipeline (Get("http://some.url/"))
    r.map(_.entity.asString)
  }
}

第二个更昂贵,因为管道每次都是重新创建的,即使理论上每个ActorSystem是静态的。我更喜欢第一个解决方案,并尝试找到一种方法来传播WebClient通过您的应用程序(通过使用蛋糕模式,通过显式传递,或使用其他依赖注入技术)。