С вашим кодом мало проблем.
Вы определяете класс дела final case class Inc()
, но отправляете объект-компаньон actor1 ! Inc
. Тем не менее, вы все равно сопоставляете объект-компаньон case Inc =>
, и ваш код работает. Но так не должно быть.
Другая проблема, мы храним, модифицируем и извлекаем var number: Int = 0
за пределами границ актера. И я думаю, именно поэтому у вас есть ошибки. Актер должен изменить только внутреннее состояние.
Я изменил ваш код, введя шаблон запроса , чтобы можно было извлечь значение из субъекта.
import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives._
import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.util.Timeout
import scala.concurrent.duration._
import scala.io.StdIn
object WebServer3 {
final case object IncAndGet //not a case class anymore
class ActorClass extends Actor with ActorLogging {
private var number: Int = 0 //inner state must be private and not accessible from outside of an actor
def receive = {
case IncAndGet =>
number += 1
context.sender() ! number // send current value back to sender
}
}
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
implicit val timeout: Timeout = 2.seconds
val actor1 = system.actorOf(Props[ActorClass], "SimpleActor")
val route =
path("counter") {
get {
onComplete((actor1 ? IncAndGet).mapTo[Int]) { number =>
complete(
HttpEntity(ContentTypes.`text/html(UTF-8)`,
s"<h1>You visited $number times</h1>"))
}
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
val _ = bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
}
}