1. 概要

Playフレームワークの使いやすいAPIは、アプリケーションの構成の管理を簡素化します。 これらのAPIの使用方法を学ぶことは、フレームワークを効果的に使用するための重要な最初のステップです。

このチュートリアルでは、Scalaを使用してPlayアプリケーションの構成データにアクセスする方法を学習します。

2. セットアップを再生

この例では、最新バージョンのPlayである2.8.2を使用します。 ただし、ここに示されている内容の多くは、2.4までさかのぼるバージョンのPlayで機能します。

新しいPlayアプリケーションを作成するには、sbtgiter8Playテンプレートplay-scala-seed.g8を使用するのが最も簡単な方法です。

sbt new playframework/play-scala-seed.g8

テンプレートは、プロジェクトの名前と組織のトップレベルドメイン名の入力を求めます。 後者は、基本パッケージの名前空間のデフォルトとして使用されます。 さらに重要なのは、スケルトンPlayアプリケーションを作成することです。

Play構成ファイルは /conf/application.conf

3. 構成ファイル形式

Javaプロパティファイルと同様の構文を使用して、Play構成ファイルを記述できます。

player.name = "Player 1"
player.email = "[email protected]"
player.age = 18
player.twitterHandle = null
player.signUpDate = "2020-09-22T10:10:06"

またはJSONを彷彿とさせる構造:

player {
  name = "Player 1"
  email = "[email protected]"
  age = 18
  twitterHandle = null
  signUpDate = "2020-09-22T10:10:06"
}

これらの形式は両方とも同じ値を指定します。

3.1. 構成値のオーバーライド

構成で同じキー/値を複数回指定することはエラーではありません。 基本的な経験則では、最新の定義が優先されます。 構文を使用してこれを利用し、環境変数から構成変数を設定できます。

myApp.apiKey= null
myApp.apiKey= ${?MYAPP_APIKEY}

ここでは、myApp.apiKeyのデフォルト値がnullであるが、環境変数MYAPP_APIKEYから設定できることを指定しています。 この環境変数は、ホスティングプラットフォームによって設定されるか、アプリがDockerイメージでホストされている場合は、コマンドラインから渡されます。

4. 主なScalaAPI

Playバージョン2.4以降、Play構成にアクセスするための推奨される方法は、play.api.Configurationのインスタンスをコンポーネントに挿入することです。

class MyService @Inject() (configuration: Configuration) {
  val name = configuration.get[String]("myApp.user.name")
  val email = configuration.get[String]("myApp.user.email")
}

Configuration クラスは、アプリケーションの構成にアクセスするためのさまざまな方法を提供しますが、ほとんどの場合、使用するAPIは次のとおりです。

Configuration.get[T](path: String)(implicit loader: ConfigLoader[T]): T

configuration.get [Option [String]]( “myApp.user”)などの Option でラップされたタイプを指定することもできます。これにより、Optionが返されます。 値:

class MyService @Inject() (configuration: Configuration) {
  val name = configuration.get[Option[String]]("myApp.user.name").getOrElse("Player1")
  val email = configuration.get[Option[String]]("myApp.user.email").getOrElse("[email protected]")
}

Option でラップされた変数を、 Option.getOrElse()メソッドと組み合わせていくつかの方法で使用できます。

  1. デフォルト値–これは、オーバーライドの複数のレイヤーが存在する場合に予期しない動作を引き起こす可能性があるため、少しアンチパターンと見なされます。
  2. 欠落している値のきめ細かいエラー処理–指定された構成変数が定義されていない場合、アプリケーション固有の例外をスローできます。

暗黙のConfigLoaderは、ここでのパズルの重要な部分です。Playアプリケーションの構成の値を特定のScalaタイプに変換する役割を果たします。 Playは、ほとんどの場合をカバーする多数のConfigLoaderを提供します。 これらの範囲は、 String Int 、および Boolean のサポートから、SeqDurationなどのより複雑なタイプまでです。[ X142X]

5. カスタムデータ型

ConfigLoader を使用すると、構成データのカスタムデータ型へのマッピングを簡単にサポートできます。 前に示したプレーヤー構成でこれをどのように行うかを見てみましょう。

まず、取得したいフィールドを持つScalaケースクラスを記述します。 予想どおり、 Option 特性でラップすることにより、オプションのフィールドを指定できます。

case class PlayerInfo(
    name: String,
    email: String,
    age: Int,
    signUpDate: Date,
    twitterHandle: Option[String] = None
)

次に、新しいタイプによってパラメーター化された暗黙のConfigLoaderを定義するコンパニオンオブジェクトを記述します。

object PlayerInfo {
  implicit val playerInfoConfigLoader: ConfigLoader[PlayerInfo] =
    (rootConfig: Config, path: String) => {
      val config = rootConfig.getConfig(path)
      new PlayerInfo(
        config.getString("name"),
        config.getString("email"),
        config.getInt("age"),
        javax.xml.bind.DatatypeConverter
          .parseDateTime(config.getString("signUpDate"))
          .getTime,
        Try(config.getString("twitterHandle")).toOption
      )
    }
}

これで、PlayerInfoクラスのインスタンスを直接ロードできます。

val playerInfo: PlayerInfo = configuration.get[PlayerInfo]("player")

これはやり過ぎのように思えるかもしれません。このクラスを1か所でしか使用していない場合は、おそらくそうです。 ただし、再利用可能なコードを作成する場合は、構成データの構造を簡単にカプセル化できることを知っておくと便利です。

6. 結論

この記事では、Playアプリケーションの構成データへのアクセスについて紹介し、説明しました。 ご覧のとおり、Playを使用すると、既存のデータ型として、またはアプリケーション固有のデータ型としてそのデータにアクセスする場合でも、これを非常に簡単に行うことができます。 いつものように、完全なソースコードはGitHubにあります。