如何使用actor接收http请求和其他actor的请求?

How to use actor to receive http requests and requests from other actors?

我希望 TestHttp class 能够接收来自其他参与者的 http 请求或消息。我该怎么做?

代码:

object Main extends App with SimpleRoutingApp {
  implicit val system = ActorSystem("system")
  import system.dispatcher
  implicit val timeout = Timeout(240.seconds)

  startServer(interface = "localhost", port = 3000) {
    get {
      path("register" / IntNumber) { n =>
        respondWithMediaType(MediaTypes.`application/json`) { ctx =>
          val future = IO(Http) ? Bind(system.actorOf(Props[TestHttp]), interface = "localhost", port = 3000 + n)
          future onSuccess {
            case Http.Bound(msg) => ctx.complete(s"Ok:"+msg)
            case _ => ctx.complete("...")
          }
        }
      } // : Route == RequestContext => Unit
    } // : Route
  }
}

trait TestHttpService extends HttpService {
  val oneRoute = {
        path("test") {
          complete("test")
        }
  }
}

class TestHttp extends Actor with TestHttpService {
  def actorRefFactory = context
  val sealedRoute = sealRoute(oneRoute) 
    def receive = {
      // case HttpRequest(GET, Uri.Path("/ping"), _, _, _) => //not working
      //   sender ! HttpResponse(entity = "PONG")
      case ctx: RequestContext => sealedRoute(ctx) //not working

    } 
  // def receive = runRoute(oneRoute) //it works
}

Actor.Receive是偏函数,取Any值和returnsUnitPartialFunction[Any, Unit]),所以你可以通过常规PF组合来完成.

HttpService.runRoutereturnsActor.Receive(参见https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/HttpService.scala#L31

所以,您的解决方案是:

class TestHttp extends Actor with TestHttpService {
  def actorRefFactory = context
  val sealedRoute = sealRoute(oneRoute) 
    def receive = {
        case s: String => println(s"Just got string $s")
    } orElse runRoute(oneRoute)
}