2015-08-14 1 views
7

Я использую Акку-HTTP 1.0, и я хотел бы использовать маршрут определяется какКак заполнить заявку на другом актер при использовании Акки-клиенте

def route: Route = path("") { 
    // start actor with requestContext 
    // call requestContext.complete(...) in actor with the result 
} 

Как достичь этого?

+2

Маршрут akka-http полностью основан на будущем, то есть «Маршрут» является псевдонимом типа для «RequestContext => Future [RouteResult]». Итак, в любом случае вам нужно немедленно вернуть «Будущее [RouteResult]». Для взаимодействия с актерами это обычно делается с использованием шаблона akka ask для отправки сообщения игроку-обработчику и мгновенного получения значения Future, с помощью которого вы можете выполнить запрос. – jrudolph

ответ

7

Разрабатывая комментарий @ jrudolph, приведенный ниже код удовлетворяет вашим требованиям по отправке значений RequestContext актеру. В вашем вопросе указывалось, что вам нужен новый актер для каждого запроса; однако в приведенном ниже коде используется тот же Актер для всех запросов, которые, по моему мнению, являются более эффективным/вероятным вариантом использования. При создании актера всегда можно перемещать внутри handleRequest.

Сначала нужен актер для обработки запроса на ответ:

import akka.actor.Actor 
import akka.http.scaladsl.server.{RequestContext, RouteResult} 
import akka.http.scaladsl.model.HttpResponse 

class RequestActor extends Actor { 

    //business logic - returns empty HttpResponse 
    def handleRequestMessage(requestContext : RequestContext) = 
    RouteResult.Complete(new HttpResponse()) 

    override def receive = { 
    case reqContext : RequestContext => 
     sender ! handleRequestMessage(reqContext) 
    } 
}//end class RequestActor 

Теперь создать функцию полезности для запроса Актер:

import akka.actor.ActorRef 
import scala.concurrent.Future 
import akka.pattern.ask 

object RequestActor { 
    val handleRequest : ActorRef => RequestContext => Future[RouteResult] = 
    (actorRef) => 
     (requestContext) => 
     ask(actorRef,reqContext).mapTo[RouteResult] 
} 

И все, что осталось сделать, это провод все вместе в службу:

import akka.actor.{ActorSystem, Props} 
import akka.stream.ActorMaterializer 
import akka.http.scaladsl.Http 
import akka.http.scaladsl.server.Directives.{get,path} 
import akka.util.Timeout 

object RouteActorTest extends App { 
    implicit val as = ActorSystem("RouteActorTest") 
    implicit val timeout = new Timeout(1000) 

    val sendRequestToActor : RequestContext => Future[RouteResult] = 
    RequestActor handleRequest (as actorOf Props[RequestActor])  

    val route = path("")(get(sendRequestToActor)) 

    //rest of application... 

}//end object RouteActorTest 
2

вы можете попробовать еще лучше:

package controllers 

import akka.actor.{Actor, ActorSystem, Props} 
import akka.stream.ActorMaterializer 

import scala.concurrent.{Await, Future} 
import akka.http.scaladsl.server.Directives._ 
import akka.stream.ActorMaterializer 
import akka.util.Timeout 
import akka.pattern.ask 
import scala.concurrent.Await 
import scala.concurrent.duration._ 
import scala.io.StdIn 
import akka.actor._ 

import akka.util.Timeout 


case object Message 

class TestActor(name:String) extends Actor { 
    def receive = { 
    case Message => 
     sender ! "Testing Ask pattern Approach" 
     println(s"hello from $name") 

    case _ => 

     println("that was unexpected") 
    } 
} 

object AskTest extends App { 

    implicit val system= ActorSystem("myactor") 
    implicit val material=ActorMaterializer() 

// implicit val props=Props.empty 
implicit val timeout = Timeout(5 seconds) 
    implicit val result =system.actorOf(Props(new TestActor("TestingName")),name = "Scala") 

    val future3:Future[String]= ask(result ,Message).mapTo[String] 
    val results = Await.result(future3, 2 seconds) 
    println(results) 
} 
Смежные вопросы