2015-06-19 8 views
5

Wir schauen uns die Verwendung von Akka-HTTP Java API an - mit Routing DSL.Wie reagiert man mit dem Ergebnis eines Schauspieleranrufs?

Es ist nicht klar, wie die Routing-Funktionalität verwendet wird, um auf eine HttpRequest reagieren; einen Untyped Akka Actor verwenden. Zum Beispiel, bei der Abstimmung eines Route-Pfades, wie übergeben wir die Anfrage an einen "Handler" ActorRef, der dann mit einer HttpResponse auf eine asynchrone Weise antwortet?

Eine ähnliche Frage wurde auf Akka-User Mailing-Liste, aber ohne Follow-up-Lösungen als solche - https://groups.google.com/d/msg/akka-user/qHe3Ko7EVvg/KC-aKz_o5aoJ.

Antwort

5

Dies kann mit einer Kombination der onComplete Direktive und der ask Muster erreicht werden.

Im folgenden Beispiel wird der RequestHandlerActor Aktor verwendet, um eine HttpResponse basierend auf der zu erstellen. Dieser Darsteller wird innerhalb der Route gefragt.

Ich habe nie Java für den Code verwendet, so dass meine Antwort in Scala ist.

import scala.concurrent.duration._ 
import akka.actor.ActorSystem 
import akka.http.scaladsl.model.HttpResponse 
import akka.http.scaladsl.model.HttpRequest 
import akka.actor.Actor 
import akka.http.scaladsl.server.Directives._ 
import akka.actor.Props 
import akka.pattern.ask 
import akka.util.Timeout 
import scala.util.{Success, Failure} 
import akka.http.scaladsl.model.StatusCodes.InternalServerError 

class RequestHandlerActor extends Actor { 
    override def receive = { 
    case httpRequest : HttpRequest => 
     sender() ! HttpResponse(entity = "actor responds nicely") 
    } 
} 

implicit val actorSystem = ActorSystem() 
implicit val timeout = Timeout(5 seconds) 

val requestRef = actorSystem actorOf Props[RequestHandlerActor] 

val route = 
    extractRequest { request => 
    onComplete((requestRef ? request).mapTo[HttpResponse]) { 
     case Success(response) => complete(response) 
     case Failure(ex) => 
     complete((InternalServerError, s"Actor not playing nice: ${ex.getMessage}")) 
    } 
    } 

Diese Route kann dann wie jeder andere Fluss übergeben in die bindAndHandle Verfahren verwendet werden.

1

Ich habe die Lösung für das gleiche Problem gesucht, wie vom Autor der Frage beschrieben. Schließlich kam ich für die Routenerstellung auf den folgenden Java-Code auf:

ActorRef ref = system.actorOf(Props.create(RequestHandlerActor.class)); 

    return get(() -> route(
      pathSingleSlash(() -> 
        extractRequest(httpRequest -> { 
         Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS)); 
         CompletionStage<HttpResponse> completionStage = PatternsCS.ask(ref, httpRequest, timeout) 
           .thenApplyAsync(HttpResponse.class::cast); 

         return completeWithFuture(completionStage); 
        }) 
      )) 
    ); 

Und RequestHandlerActor ist:

public class RequestHandlerActor extends UntypedActor { 
    @Override 
    public void onReceive(Object msg) { 
     if (msg instanceof HttpRequest) { 
      HttpResponse httpResponse = HttpResponse.create() 
        .withEntity(ContentTypes.TEXT_HTML_UTF8, 
          "<html><body>Hello world!</body></html>"); 

      getSender().tell(httpResponse, getSelf()); 
     } else { 
      unhandled(msg); 
     } 
    } 
} 
Verwandte Themen