Akka Http - мультируты и простое отражение кода с импликатами - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть простой 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)
  }
}

Теперь я хотел бы реорганизовать этот код и переместить этот фрагмент в отдельный метод /класс / объект и т. д.:

val game = new GameRouting
val rate = new RateRouting
val routes: Route = game.route ~ rate.route

Но эти классы (GameRouting и RateRouting) используют implicit в конструкторах, и я не могу просто переместить этот код в отдельное место.Как мне провести рефакторинг этого кода, чтобы получить то, что я хочу?

Мой другой вопрос - классы маршрутов (GameRouting и RateRouting) должны быть class или case class?Это GameRouting класс:

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, я не смогу получить доступ к полю routes из Main объекта.Как это исправить или написать лучше?Может быть, есть основные вопросы, но я все еще изучаю Scala и Akka уже несколько недель.

1 Ответ

0 голосов
/ 23 декабря 2018

Вы можете просто переместить ваши импликации в отдельный объект:

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.

...