Akka Http - 多路由和隐式代码的简单反射
Akka Http - multiroutes and simple reflection of code with implicits
我有一个简单的 Main
对象,它以这种方式为我的两个服务创建 routes
:
object GameApp extends App {
val config = ConfigFactory.load()
val host = config.getString("http.host")
val port = config.getInt("http.port")
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
Http().bindAndHandle(routes, host, port) map {
binding => println(s"Server start on ${binding.localAddress}")
} recover {
case ex => println(s"Server could not start on ${host}:${port}", ex.getMessage)
}
}
现在,我想重构这段代码并将这段代码移到单独的 method/class/object 等中:
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
但是这个 classes(GameRouting
和 RateRouting
)在构造函数中使用 implicit
,我不能简单地将这段代码移到单独的地方。
我应该如何重构这段代码以获得我想要的?
我的另一个问题是 - 路由 classes(GameRouting
和 RateRouting
)应该是 class
还是 case class
?这是 GameRouting
class:
trait Protocols extends SprayJsonSupport with DefaultJsonProtocol {
implicit val gameFormat = jsonFormat4(Game)
}
class GameRouting(implicit executionContext: ExecutionContext) extends Protocols {
val gameService = new GameService
val route: Route = {
pathPrefix("games") {
pathEndOrSingleSlash {
get {
complete {
gameService.getGames()
}
} ~
post {
entity(as[Game]) { gameForCreate =>
createGame(gameForCreate)
}
}
} ~
pathPrefix(LongNumber) { id =>
get {
complete {
gameService.getGame(id)
}
} ~ put {
entity(as[Game]) { gameForUpdate =>
complete {
gameService.update(gameForUpdate)
}
}
}
}
}
}
private def createGame(gameForCreate: Game) = {
onComplete(gameService.createGame(gameForCreate)) {
case Success(created) => complete(StatusCodes.Created, created)
case Failure(exception) => complete(StatusCodes.BadRequest, s"An error: $exception")
}
}
}
如果我做到了 case
,我将无法从 Main
对象访问字段 routes
。如何解决这个问题或以更好的方式编写它?也许有一些基本问题,但几周以来我一直在学习 Scala 和 Akka。
您可以将隐式对象移动到单独的对象中:
object GameAppImplicits {
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
}
然后在需要的时候导入:
import yourpackage.GameAppImplicits._
对于你的第二个问题,case 类 通常用于对不可变数据建模。在这种情况下你真的不需要任何功能,那种情况 类 给你(比如自动 toString
、equals
、copy
等),所以我会说最好只使用普通 class
.
我有一个简单的 Main
对象,它以这种方式为我的两个服务创建 routes
:
object GameApp extends App {
val config = ConfigFactory.load()
val host = config.getString("http.host")
val port = config.getInt("http.port")
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
Http().bindAndHandle(routes, host, port) map {
binding => println(s"Server start on ${binding.localAddress}")
} recover {
case ex => println(s"Server could not start on ${host}:${port}", ex.getMessage)
}
}
现在,我想重构这段代码并将这段代码移到单独的 method/class/object 等中:
val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route
但是这个 classes(GameRouting
和 RateRouting
)在构造函数中使用 implicit
,我不能简单地将这段代码移到单独的地方。
我应该如何重构这段代码以获得我想要的?
我的另一个问题是 - 路由 classes(GameRouting
和 RateRouting
)应该是 class
还是 case class
?这是 GameRouting
class:
trait Protocols extends SprayJsonSupport with DefaultJsonProtocol {
implicit val gameFormat = jsonFormat4(Game)
}
class GameRouting(implicit executionContext: ExecutionContext) extends Protocols {
val gameService = new GameService
val route: Route = {
pathPrefix("games") {
pathEndOrSingleSlash {
get {
complete {
gameService.getGames()
}
} ~
post {
entity(as[Game]) { gameForCreate =>
createGame(gameForCreate)
}
}
} ~
pathPrefix(LongNumber) { id =>
get {
complete {
gameService.getGame(id)
}
} ~ put {
entity(as[Game]) { gameForUpdate =>
complete {
gameService.update(gameForUpdate)
}
}
}
}
}
}
private def createGame(gameForCreate: Game) = {
onComplete(gameService.createGame(gameForCreate)) {
case Success(created) => complete(StatusCodes.Created, created)
case Failure(exception) => complete(StatusCodes.BadRequest, s"An error: $exception")
}
}
}
如果我做到了 case
,我将无法从 Main
对象访问字段 routes
。如何解决这个问题或以更好的方式编写它?也许有一些基本问题,但几周以来我一直在学习 Scala 和 Akka。
您可以将隐式对象移动到单独的对象中:
object GameAppImplicits {
implicit val system = ActorSystem("game-service")
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
}
然后在需要的时候导入:
import yourpackage.GameAppImplicits._
对于你的第二个问题,case 类 通常用于对不可变数据建模。在这种情况下你真的不需要任何功能,那种情况 类 给你(比如自动 toString
、equals
、copy
等),所以我会说最好只使用普通 class
.