ドキュメント

§設定ファイルの構文と機能

Playで使用される設定ファイルは、Typesafe configライブラリに基づいています。

Playアプリケーションの設定ファイルは、conf/application.confで定義する必要があります。これはHOCON形式を使用します。

application.confファイルだけでなく、設定は他の場所からも読み込まれます。

Configの慣用的な使い方は、すべての設定キーを、reference.confまたはapplication.confのいずれかで定義することです。キーに合理的なデフォルト値がない場合は、通常、"値がない"ことを示すためにnullに設定します。

§代替設定ファイルの指定

実行時に、デフォルトのapplication.confはクラスパスからロードされます。システムプロパティを使用して、別の設定ソースを強制できます。

これらのシステムプロパティは、application.confの代替を指定するものであり、追加するものではありません。application.confファイルからいくつかの値を使用したい場合は、ファイルの先頭にinclude "application"と記述して、別の.confファイルにapplication.confを含めることができます。新しい.confファイルにapplication.confの設定を含めたら、上書きしたい設定を指定できます。

§コントローラーからの使用

設定は、依存性注入(ScalaまたはJava)のおかげで、デフォルト設定またはカスタム設定を使用して、コントローラー(またはコンポーネント)で使用できます。

Scala
import javax.inject._

import play.api.Configuration

class MyController @Inject() (config: Configuration) {
  // ...
}
Java
package controllers

import com.typesafe.config.Config;
import javax.inject.Inject;
import play.mvc.Controller;

public class MyController extends Controller {

  private final Config config;

  @Inject
  public MyController(Config config) {
    this.config = config;
  }
}

§Pekkoでの使用

Pekkoは、Playアプリケーションに定義されているものと同じ設定ファイルを使用します。つまり、application.confファイルでPekkoのあらゆるものを設定できます。Playでは、Pekkoはpekko設定からではなく、play.pekko設定内から設定を読み取ります。

§runコマンドでの使用

runコマンドでアプリケーションを実行する場合、設定について知っておくべきいくつかの特別なことがあります。

§追加のdevSettings

build.sbtrunコマンドの追加設定を構成できます。これらの設定は、アプリケーションをデプロイするときには使用されません。

PlayKeys.devSettings += "play.server.http.port" -> "8080"

§application.confのHTTPサーバー設定

runモードでは、PlayのHTTPサーバー部分はアプリケーションがコンパイルされる前に起動します。これは、HTTPサーバーが起動時にapplication.confファイルにアクセスできないことを意味します。runコマンドを使用中にHTTPサーバーの設定を上書きしたい場合は、application.confファイルを使用できません。代わりに、システムプロパティまたは上記に示すdevSettings設定を使用する必要があります。サーバー設定の例は、HTTPポートです。

> run -Dhttp.port=1234

他のサーバー設定はこちらを参照してください。これらのサーバー設定でわかるように、ポートまたはアドレスがPlayKeys.devSettingsなどを介してまだ定義されていない場合、http(s)ポートおよびアドレスは、設定キーPLAY_HTTP_PORTPLAY_HTTPS_PORT、およびPLAY_HTTP_ADDRESSにフォールバックします。これらの設定キーは置換であるため、環境変数からも定義できます(たとえば、LinuxでBashを使用する場合)。

export PLAY_HTTP_PORT=9001
export PLAY_HTTPS_PORT=9002
export PLAY_HTTP_ADDRESS=127.0.0.1

開発モード(runコマンドで使用されるモード)用にPekko設定をカスタマイズする必要がある場合は、特定の名前空間もあります。PlayKeys.devSettingsの設定にplay.pekko.dev-modeを付加する必要があります。例:

PlayKeys.devSettings += "play.pekko.dev-mode.pekko.cluster.log-info" -> "off"

これは、開発モードで使用されるPekko ActorSystemと、アプリケーション自体で使用されるActorSystemの間に競合がある場合に特に役立ちます。

§HOCONの構文

HOCONはJSONと類似点があります。もちろん、http://json.org/でJSON仕様を見つけることができます。

§JSONから変更なし

§コメント

//または#と次の改行の間にあるものはすべてコメントとみなされ、無視されます。ただし、//または#が引用符で囲まれた文字列内にある場合は除きます。

§ルート中括弧の省略

JSONドキュメントは、ルートに配列またはオブジェクトが必要です。空のファイルは無効なドキュメントであり、文字列などの配列ではないオブジェクトではない値のみを含むファイルも無効です。

HOCONでは、ファイルが角かっこまたは中かっこで始まらない場合、{}中かっこで囲まれているかのように解析されます。

HOCONファイルは、先頭の{を省略しているが、閉じの}がまだある場合、無効です。中かっこはバランスが取れている必要があります。

§キーと値の区切り記号

=文字は、JSONで:が許可されている場所(つまり、キーを値から分離する場合)であればどこでも使用できます。

キーの後に{が続く場合、:または=を省略できます。したがって、"foo" {}"foo" : {}"を意味します。

§カンマ

配列内の値、およびオブジェクト内のフィールドは、それらの間に少なくとも1つのASCII改行(\n、10進数値10)がある限り、カンマを必要としません。

配列内の最後の要素またはオブジェクト内の最後のフィールドの後に、単一のカンマを付けることができます。この余分なカンマは無視されます。

§重複キー

JSON仕様では、同じオブジェクト内の重複キーをどのように処理する必要があるかを明確にしていません。HOCONでは、後で出現する重複キーは、両方の値がオブジェクトでない限り、先に現れるキーを上書きします。両方の値がオブジェクトの場合、オブジェクトはマージされます。

注:これは、JSONが重複キーに動作を要求すると仮定した場合、HOCONをJSONの非スーパーセットにする可能性があります。ここでの仮定は、重複キーは無効なJSONであるということです。

オブジェクトをマージするには

オブジェクトのマージは、最初にキーを別の値に設定することで防ぐことができます。これは、マージが常に一度に2つの値に対して行われるためです。もしキーをオブジェクト、非オブジェクト、そしてオブジェクトの順に設定した場合、最初に非オブジェクトがオブジェクトにフォールバックし(非オブジェクトが常に優先)、次にオブジェクトが非オブジェクトにフォールバックします(マージは行われず、オブジェクトが新しい値になります)。したがって、2つのオブジェクトが互いに影響し合うことはありません。

以下の2つは等価です。

{
    "foo" : { "a" : 42 },
    "foo" : { "b" : 43 }
}

{
    "foo" : { "a" : 42, "b" : 43 }
}

以下の2つも等価です。

{
    "foo" : { "a" : 42 },
    "foo" : null,
    "foo" : { "b" : 43 }
}

{
    "foo" : { "b" : 43 }
}

"foo"nullに中間設定することで、オブジェクトのマージが防止されます。

§キーとしてのパス

キーが複数の要素を持つパス式の場合、最後の要素以外の各パス要素に対してオブジェクトを作成するように展開されます。最後のパス要素は値と組み合わされ、最深のネストされたオブジェクトのフィールドになります。

言い換えると

foo.bar : 42

は、以下と等価です。

foo { bar : 42 }

そして

foo.bar.baz : 42

は、以下と等価です。

foo { bar { baz : 42 } }

などとなります。これらの値は通常の方法でマージされます。つまり、以下を意味します。

a.x : 42, a.y : 43

は、以下と等価です。

a { x : 42, y : 43 }

パス式は値の連結のように機能するため、キーに空白を含めることができます。

a b c : 42

は、以下と等価です。

"a b c" : 42

パス式は常に文字列に変換されるため、通常は別の型となる単一の値であっても文字列になります。

特別なルールとして、引用符で囲まれていない文字列 include は、キー内のパス式の先頭に置くことはできません。これは、特別な解釈があるためです(下記参照)。

§置換

置換は、構成ツリーの他の部分を参照する方法です。

構文は、${pathexpression} または ${?pathexpression} です。ここで、pathexpression は上記で説明したパス式です。このパス式は、オブジェクトキーに使用できるものと同じ構文を持ちます。

${?pathexpression}? の前には、空白を置くことはできません。3つの文字 ${? は、正確にそのようにグループ化されている必要があります。

構成ツリー内に見つからない置換については、実装はシステム環境変数やその他の外部構成ソースを参照して解決を試みることがあります。(環境変数の詳細については、後述のセクションで説明します。)

置換は引用符で囲まれた文字列内では解析されません。置換を含む文字列を取得するには、引用符で囲まれていない部分に置換を含む値の連結を使用する必要があります。

key : ${animal.favorite} is my favorite animal

または、置換以外の部分を引用符で囲むこともできます。

key : ${animal.favorite}" is my favorite animal"

置換は、構成内のパスを検索することによって解決されます。パスはルート構成オブジェクトから始まり、つまり「相対的」ではなく「絶対的」です。

置換処理は最後の解析ステップとして実行されるため、置換は構成内で先を見ることができます。構成が複数のファイルで構成されている場合、別のファイルから値を取得することさえあります。キーが複数回指定されている場合、置換は常に最後に割り当てられた値(マージされたオブジェクトまたは最後に設定された非オブジェクト値)に評価されます。

構成が値を null に設定した場合、外部ソースで検索すべきではありません。残念ながら、後続の構成ファイルでこれを「元に戻す」方法はありません。ルートオブジェクトに { "HOME" : null } がある場合、${HOME} は環境変数を参照しません。言い換えれば、JavaScript の delete 操作に相当するものはありません。

置換が構成に存在するどの値とも一致せず、外部ソースによって解決されない場合、それは未定義になります。${foo} 構文を持つ未定義の置換は無効であり、エラーを生成する必要があります。

${?foo} 構文を持つ置換が未定義の場合

置換は、オブジェクトフィールド値と配列要素(値の連結)でのみ許可されており、キーや他の置換(パス式)の内部にネストすることはできません。

置換は、任意の型の値(数値、オブジェクト、文字列、配列、true、false、null)に置き換えられます。置換が値の一部のみである場合、型は保持されます。それ以外の場合は、値が連結されて文字列が形成されます。

循環置換は無効であり、エラーを生成する必要があります。

ただし、実装では、オブジェクトが自分自身のパスを参照できるように注意する必要があります。たとえば、これは機能する必要があります。

bar : { foo : 42,
        baz : ${bar.foo}
      }

ここで、実装が ${bar.foo} の置換を解決する一環として、bar 内のすべての置換を解決した場合、循環が発生します。実装は、bar オブジェクト全体を再帰するのではなく、bar 内の foo フィールドのみを解決する必要があります。

§インクルード

§インクルード構文

インクルードステートメントは、引用符で囲まれていない文字列 include と、その直後に続く単一の引用符で囲まれた文字列で構成されます。インクルードステートメントは、オブジェクトフィールドの代わりに表示できます。

引用符で囲まれていない文字列 include が、オブジェクトキーが予期されるパス式の先頭に現れる場合、それはパス式またはキーとして解釈されません。

代わりに、次の値は引用符で囲まれた文字列である必要があります。引用符で囲まれた文字列は、インクルードされるファイル名またはリソース名として解釈されます。

引用符で囲まれていない include と引用符で囲まれた文字列は、構文的にオブジェクトフィールドの代わりとなり、通常のコンマで区切られます(通常どおり、改行がある場合はコンマを省略できます)。

キーの先頭にある引用符で囲まれていない include の後に、単一の引用符で囲まれた文字列以外のものが続く場合、それは無効であり、エラーを生成する必要があります。

引用符で囲まれていない include と引用符で囲まれた文字列の間には、改行を含む任意の量の空白を置くことができます。

値の連結は、include の「引数」に対しては実行されません。引数は単一の引用符で囲まれた文字列である必要があります。置換は許可されておらず、引数は引用符で囲まれていない文字列や他の種類の値であってはなりません。

引用符で囲まれていない include は、キーのパス式の先頭でない場合は特別な意味を持ちません。

キーの後ろに出現する可能性があります。

# this is valid
{ foo include : 42 }
# equivalent to
{ "foo include" : 42 }

オブジェクトまたは配列の値として出現する可能性があります。

{ foo : include } # value is the string "include"
[ include ]       # array of one string "include"

"include" という単語で始まるキーが必要な場合は、"include" を引用符で囲むことができます。引用符で囲まれていない include のみが特別です。

{ "include" : 42 }

§インクルードセマンティクス:マージ

インクルードファイルにはインクルードステートメントが含まれており、インクルードされるファイルはインクルードステートメントで指定されたファイルです。(これらはファイルシステムの通常のファイルである必要はありませんが、当面はそうであると仮定します。)

インクルードされるファイルには、配列ではなくオブジェクトが含まれている必要があります。これは、JSONとHOCONの両方がドキュメント内のルート値として配列を許可するため、重要です。

インクルードされるファイルにルート値として配列が含まれている場合、それは無効であり、エラーを生成する必要があります。

インクルードされるファイルは解析され、ルートオブジェクトが生成される必要があります。ルートオブジェクトのキーは、概念的にはインクルードファイルのインクルードステートメントに代入されます。

§インクルードセマンティクス:置換

インクルードファイル内の置換は、2つの異なるパスで検索されます。最初に、インクルードされたファイルのルートに対する相対パス。次に、インクルード構成のルートに対する相対パスです。

置換は最後のステップとして、解析に行われることを思い出してください。単一のファイルに対してではなく、アプリケーション全体の構成に対して行う必要があります。

したがって、インクルードファイルに置換が含まれている場合は、アプリケーションの構成ルートに対する相対パスになるように「修正」する必要があります。

たとえば、ルート構成が次のようであるとします。

{ a : { include "foo.conf" } }

そして、「foo.conf」は次のようになる可能性があります。

{ x : 10, y : ${x} }

「foo.conf」を単独で解析すると、${x} はパス x の値である10に評価されます。ただし、「foo.conf」をキー a のオブジェクトにインクルードする場合は、${x} ではなく ${a.x} に修正する必要があります。

ルート構成が a.x を次のように再定義するとします。

{
    a : { include "foo.conf" }
    a : { x : 42 }
}

次に、「foo.conf」の ${x}${a.x} に修正されているため、10 ではなく 42 に評価されます。置換は、構成全体を解析した後に行われます。

ただし、インクルードファイルがアプリケーションのルート構成を参照することを意図している場合はたくさんあります。たとえば、システムプロパティまたは参照構成から値を取得する場合などです。したがって、「修正された」パスのみを検索するだけでは十分ではなく、元のパスも検索する必要があります。

§インクルードセマンティクス:ファイルが見つからない場合

インクルードされたファイルが存在しない場合、インクルードステートメントは黙って無視される必要があります(インクルードされたファイルに空のオブジェクトのみが含まれているかのように)。

§インクルードセマンティクス:リソースの検索

概念的に言えば、インクルードステートメントの引用符で囲まれた文字列は、解析されているものと「隣接」しており、解析されているものと同じタイプであるファイルまたはその他のリソースを識別します。「隣接」の意味と文字列自体は、リソースの種類ごとに個別に指定する必要があります。

実装は、インクルードをサポートするリソースの種類によって異なる場合があります。

Java仮想マシンにおいて、インクルード文がインクルード元のリソースの「隣接する」ものを特定しない場合、実装はクラスパスリソースにフォールバックすることが望ましいかもしれません。これにより、ファイルやURLにある設定がクラスパスリソースにアクセスできるようになります。

Javaクラスパス上にあるリソースの場合

ファイルシステム上のプレーンファイルの場合

URL

§期間形式

期間のサポートされる単位文字列は大文字と小文字が区別され、小文字にする必要があります。以下の文字列のみがサポートされています。

§期間形式

java.time.Periodでサポートされる単位文字列は大文字と小文字が区別され、小文字にする必要があります。以下の文字列のみがサポートされています。

§時間量形式

これは、上記の単位文字列を使用したjava.time.Periodまたはjava.time.Durationのどちらかです。期間になることが優先されます。つまり、mは分を意味するため、月を指定するには長い形式(momonthmonths)を使用する必要があります。

§バイト単位のサイズ形式

単一バイトの場合、以下の文字列のみがサポートされています。

10の累乗の場合、以下の文字列のみがサポートされています。

2の累乗の場合、以下の文字列のみがサポートされています。

§システムプロパティによる従来のオーバーライド

Javaシステムプロパティは、application.confファイルおよびreference.confファイルにある設定をオーバーライドします。これにより、コマンドラインで設定オプションを指定できます。たとえば、sbt -Dkey=value runです。

:PlayはテストのためにJVMをフォークするため、テストでコマンドラインオーバーライドを使用するには、テストで使用する前にbuild.sbtTest / Keys.fork := falseを追加する必要があります。

次へ: アプリケーションシークレットの設定


このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。 ドキュメントのガイドラインを読んだ後、プルリクエストを自由に貢献してください。質問や共有するアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めましょう。