Wenn ich eine Ruhe-API anrufe, möchte ich die Route des Schauspielers auf andere Routen umschalten. Bitte beachten Sie den folgenden Code.
Ein paar Fragen:
- Der Code kompiliert gut, aber wenn die App gestartet wird und ein http-Aufruf gemacht wird, bekomme ich eine konfigurierte Registrierung Timeout von 1 Sekunde abgelaufen, stoppe Nachricht und ich bekomme keine Antwort vom Server.
- Ich möchte in der Lage sein, Routing zu einem anderen Satz von Routen durch API zu wechseln.
gemacht
package com.example
import akka.actor.Actor
import akka.io.IO
import spray.httpx.RequestBuilding._
import spray.http.MediaTypes._
import spray.routing.{RoutingSettings, RejectionHandler, ExceptionHandler, HttpService}
import spray.util.LoggingContext
import scala.concurrent.Future
import spray.can.Http
import spray.http._
import akka.util.Timeout
import HttpMethods._
import akka.pattern.ask
import akka.event.Logging
import scala.concurrent.duration._
case object Swap
class MyServiceActor extends Actor with MyService with akka.actor.ActorLogging {
implicit def actorRefFactory = context
import context._
def receive = {
case Swap =>
become {
case Swap => unbecome()
case _ => runRoute(otherRoutes)
}
case _ => runRoute(myRoute)
}
}
trait MyService extends HttpService { this: MyServiceActor =>
implicit val timeout: Timeout = Timeout(15.seconds)
implicit val system = context.system
val myRoute =
{
path("") {
get {
complete("MyRoute")
}
} ~ path("swap") {
get{
self ! Swap
complete("Swapped")
}
}
}
val otherRoutes =path("") {
get {
complete("OtherRoutes")
}
} ~ path("swap") {
get{
self ! Swap
complete("Reverted")
}
}
}
Antworten:
2 für die Antwort № 1runRoute ist eine Teilfunktion, Sie können also nicht schreiben runRoute(routeName)
um es aufzurufen - es wird nur die Funktion zurückgeben (die Routen behandelt), aber ohne sie aufzurufen; Sie sollten das Anfrageobjekt explizit übergeben:
def receive = {
case Swap =>
become {
case Swap => unbecome()
case x => val f = runRoute(otherRoutes); f(x)
}
case x => val f = runRoute(myRoute); f(x)
}
runRoute(route)
gibt eine Funktion zurück, die die Nachricht "Verbunden" handhabt. Das ist der Grund, warum Sie "Registrierungs-Timeout" -Fehler bekommen - Sie geben diese Funktion nicht von der Empfangs-Methode zurück. Wenn Sie schreiben def receive = runRoute(route)
Diese Funktion wird als Handler verwendet und alles ist in Ordnung. Aber wenn du schreibst def receive = {case _ => runRoute(route)}
nichts passiert - receive
Funktion tue nichts, weil Funktion von zurückgegeben wird runRoute(route)
geht nirgendwohin.
Und Sie können auch direkt von Ihrer Route aus "becoming / uncome" aufrufen, da Sie MyServiceActor bereits als Selbst-Typ haben. Wenn Sie separat verwenden Swap
Nachricht - Der Akteur kann seine Rolle ein wenig ändern, nachdem Sie eine erfolgreiche "Swapped" -Antwort erhalten haben (die Rollenänderung erfolgt asynchron)
case object Swap
class MyServiceActor extends Actor with MyService with akka.actor.ActorLogging {
implicit def actorRefFactory = context
import context._
def swapped = {
case x => val f = runRoute(otherRoutes); f(x)
}
def receive = {
case x => val f = runRoute(myRoute); f(x)
}
}
trait MyService extends HttpService { this: MyServiceActor =>
implicit val timeout: Timeout = Timeout(15.seconds)
implicit val system = context.system
val myRoute = {
pathSingleSlash {
get {
complete("MyRoute")
}
} ~ path("swap") {
get {
become(swapped)
complete("Swapped")
}
}
}
val otherRoutes = {
pathSingleSlash {
get {
complete("OtherRoutes")
}
} ~ path("swap") {
get{
unbecome()
complete("Reverted")
}
}
}
}
Aktualisiert: Deine Pfad-Matching ist ebenfalls falsch. Benutzen:
pathSingleSlash {
...
} ~ path("swap") {
...
}
oder
path("swap") {
...
} ~ path("") { //matches everything else
...
}
Aktualisiert2:
Stelle sicher, dass dein Akteur in deinem Main als Singleton registriert ist:
import akka.io.IO
import spray.can.Http
implicit val system = ActorSystem()
val myListener: ActorRef = Props[MyServiceActor]
IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080)
http://spray.io/documentation/1.1-SNAPSHOT/spray-can/http-server/#http-server