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(GameRoutingRateRouting)在构造函数中使用 implicit,我不能简单地将这段代码移到单独的地方。 我应该如何重构这段代码以获得我想要的?

我的另一个问题是 - 路由 classes(GameRoutingRateRouting)应该是 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 类 通常用于对不可变数据建模​​。在这种情况下你真的不需要任何功能,那种情况 类 给你(比如自动 toStringequalscopy 等),所以我会说最好只使用普通 class.