§設定ファイルの構文と機能
Playで使用される設定ファイルは、Typesafe configライブラリに基づいています。
Playアプリケーションの設定ファイルは、conf/application.conf
で定義する必要があります。これはHOCON形式を使用します。
application.conf
ファイルだけでなく、設定は他の場所からも読み込まれます。
- デフォルト設定は、クラスパスにあるすべての
reference.conf
ファイルからロードされます。ほとんどのPlay JARには、デフォルト設定を含むreference.conf
ファイルが含まれています。application.conf
の設定は、reference.conf
ファイルの設定を上書きします。 - システムプロパティを使用して設定することもできます。システムプロパティは、
application.conf
の設定を上書きします。
Configの慣用的な使い方は、すべての設定キーを、reference.conf
またはapplication.conf
のいずれかで定義することです。キーに合理的なデフォルト値がない場合は、通常、"値がない"ことを示すためにnull
に設定します。
§代替設定ファイルの指定
実行時に、デフォルトのapplication.conf
はクラスパスからロードされます。システムプロパティを使用して、別の設定ソースを強制できます。
config.resource
は、拡張子を含むリソース名(つまり、application
だけでなくapplication.conf
)を指定します。config.file
は、ファイルシステムのパスを指定します。これもベース名ではなく、拡張子を含める必要があります。
これらのシステムプロパティは、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.sbt
でrun
コマンドの追加設定を構成できます。これらの設定は、アプリケーションをデプロイするときには使用されません。
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_PORT
、PLAY_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から変更なし
- ファイルは有効なUTF-8である必要があります。
- 引用符で囲まれた文字列は、JSON文字列と同じ形式です。
- 値には、文字列、数値、オブジェクト、配列、ブール値、nullなどの型があります。
- 許可される数値形式はJSONに一致します。JSONと同様に、一部の可能性のある
浮動小数点値(NaN
など)は表現されません。
§コメント
//
または#
と次の改行の間にあるものはすべてコメントとみなされ、無視されます。ただし、//
または#
が引用符で囲まれた文字列内にある場合は除きます。
§ルート中括弧の省略
JSONドキュメントは、ルートに配列またはオブジェクトが必要です。空のファイルは無効なドキュメントであり、文字列などの配列ではないオブジェクトではない値のみを含むファイルも無効です。
HOCONでは、ファイルが角かっこまたは中かっこで始まらない場合、{}
中かっこで囲まれているかのように解析されます。
HOCONファイルは、先頭の{
を省略しているが、閉じの}
がまだある場合、無効です。中かっこはバランスが取れている必要があります。
§キーと値の区切り記号
=
文字は、JSONで:
が許可されている場所(つまり、キーを値から分離する場合)であればどこでも使用できます。
キーの後に{
が続く場合、:
または=
を省略できます。したがって、"foo" {}
は"foo" : {}"
を意味します。
§カンマ
配列内の値、およびオブジェクト内のフィールドは、それらの間に少なくとも1つのASCII改行(\n
、10進数値10)がある限り、カンマを必要としません。
配列内の最後の要素またはオブジェクト内の最後のフィールドの後に、単一のカンマを付けることができます。この余分なカンマは無視されます。
[1,2,3,]
と[1,2,3]
は同じ配列です。[1\n2\n3]
と[1,2,3]
は同じ配列です。[1,2,3,,]
は、末尾のカンマが2つあるため、無効です。[,1,2,3]
は、先頭にカンマがあるため、無効です。[1,,2,3]
は、カンマが2つ続いているため、無効です。- これらの同じカンマ規則は、オブジェクト内のフィールドにも適用されます。
§重複キー
JSON仕様では、同じオブジェクト内の重複キーをどのように処理する必要があるかを明確にしていません。HOCONでは、後で出現する重複キーは、両方の値がオブジェクトでない限り、先に現れるキーを上書きします。両方の値がオブジェクトの場合、オブジェクトはマージされます。
注:これは、JSONが重複キーに動作を要求すると仮定した場合、HOCONをJSONの非スーパーセットにする可能性があります。ここでの仮定は、重複キーは無効なJSONであるということです。
オブジェクトをマージするには
- 2つのオブジェクトのいずれか一方にのみ存在するフィールドを、マージされたオブジェクトに追加します。
- 両方のオブジェクトに存在するオブジェクト値以外のフィールドの場合、2番目のオブジェクトで見つかったフィールドを使用する必要があります。
- 両方のオブジェクトに存在するオブジェクト値のフィールドの場合、オブジェクト値は、これらの同じ規則に従って再帰的にマージする必要があります。
オブジェクトのマージは、最初にキーを別の値に設定することで防ぐことができます。これは、マージが常に一度に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
パス式は常に文字列に変換されるため、通常は別の型となる単一の値であっても文字列になります。
true : 42
は"true" : 42
になります。3.14 : 42
は"3.14" : 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}
構文を持つ置換が未定義の場合
- それがオブジェクトフィールドの値である場合、フィールドは
作成されるべきではありません。フィールドが以前に設定された
同じフィールドの値より優先されるはずの場合、以前の値が残ります。 - それが配列要素である場合、要素は追加されるべきではありません。
- それが値の連結の一部である場合、それは
空の文字列になるはずです。 foo : ${?bar}
は、bar
が
未定義の場合、フィールドfoo
の作成を回避しますが、foo : ${?bar} ${?baz}
は値の
連結になるため、bar
またはbaz
が未定義の場合、結果は
空の文字列になります。
置換は、オブジェクトフィールド値と配列要素(値の連結)でのみ許可されており、キーや他の置換(パス式)の内部にネストすることはできません。
置換は、任意の型の値(数値、オブジェクト、文字列、配列、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クラスパス上にあるリソースの場合
- インクルードされるリソースは、
getResource()
を呼び出すことによって検索されます。
インクルード元のリソースの検索に使用されるのと同じクラスローダーが使用されます。 - インクルードされるリソース名が絶対パス('/'で始まる)である場合
getResource()
には、'/'を取り除いたものを渡す必要があります。
削除されます。 - インクルードされるリソース名が'/'で始まらない場合、それは
インクルード元のリソースの「ディレクトリ」を持つ必要があります。getResource()
に渡す前に、そのディレクトリが先頭に追加されます。もし
インクルード元のリソースが絶対パスではなく('/'がない)、かつ「親
ディレクトリ」がない(単一のパス要素である)場合、インクルードされる
相対リソース名はそのままにする必要があります。 getResource()
を使用してURLを取得し、そのURLに対して
相対的にインクルードされる名前を見つけるのは間違いです。なぜなら、クラス
ローダーは、そのURLのパスと、getResource()
で扱うパスの間に
1対1のマッピングを持っている必要はないからです。
言い換えれば、「隣接する」の計算は、リソースのURLではなく
リソース名に対して行う必要があります。
ファイルシステム上のプレーンファイルの場合
- インクルードされるファイルが絶対パスである場合、それは
絶対パスのままにして、そのようにロードする必要があります。 - インクルードされるファイルが相対パスである場合、それは
インクルード元のファイルを含むディレクトリを基準に
配置する必要があります。ファイルを解析するプロセスの現在の作業ディレクトリは
インクルードされるパスを解釈する際に使用してはなりません。 - ファイルが見つからない場合、クラスパスリソースにフォールバックします。
クラスパスリソースには、パッケージ名を追加してはなりません
先頭に。それは「ルート」に対する相対パスである必要があります。これは、
先頭の「/」は削除する必要があることを意味します(絶対パスは同じです。
ルート相対なので相対パスと同じです)。「/」は、
他のクラスパスリソース内からのリソースのインクルードとの一貫性を保つために処理されます。
そこでは、リソース名がルート相対ではない可能性があり、「/」は
ルートに対する相対パスを指定することを可能にします。
URL
- ファイルシステムファイルとJavaリソースの両方で、
インクルードされる名前がURL(プロトコルで始まる)の場合、
名前をファイル名またはリソース名として扱うのではなく、URLを
ロードしようとするのが妥当な動作でしょう。 - URLからロードされたファイルの場合、「隣接する」は
URLのパスコンポーネントを解析し、最後の
パス要素をインクルードされる名前に置き換えることに基づいて行う必要があります。 - file: URLはプレーンな
ファイル名とまったく同じように動作する必要があります。
§期間形式
期間のサポートされる単位文字列は大文字と小文字が区別され、小文字にする必要があります。以下の文字列のみがサポートされています。
ns
,nanosecond
,nanoseconds
us
,microsecond
,microseconds
ms
,millisecond
,milliseconds
s
,second
,seconds
m
,minute
,minutes
h
,hour
,hours
d
,day
,days
§期間形式
java.time.Period
でサポートされる単位文字列は大文字と小文字が区別され、小文字にする必要があります。以下の文字列のみがサポートされています。
d
,day
,days
w
,week
,weeks
m
,mo
,month
,months
y
,year
,years
§時間量形式
これは、上記の単位文字列を使用したjava.time.Period
またはjava.time.Duration
のどちらかです。期間になることが優先されます。つまり、m
は分を意味するため、月を指定するには長い形式(mo
、month
、months
)を使用する必要があります。
§バイト単位のサイズ形式
単一バイトの場合、以下の文字列のみがサポートされています。
B
,b
,byte
,bytes
10の累乗の場合、以下の文字列のみがサポートされています。
kB
,kilobyte
,kilobytes
MB
,megabyte
,megabytes
GB
,gigabyte
,gigabytes
TB
,terabyte
,terabytes
PB
,petabyte
,petabytes
EB
,exabyte
,exabytes
ZB
,zettabyte
,zettabytes
YB
,yottabyte
,yottabytes
2の累乗の場合、以下の文字列のみがサポートされています。
K
,k
,Ki
,KiB
,kibibyte
,kibibytes
M
,m
,Mi
,MiB
,mebibyte
,mebibytes
G
,g
,Gi
,GiB
,gibibyte
,gibibytes
T
,t
,Ti
,TiB
,tebibyte
,tebibytes
P
,p
,Pi
,PiB
,pebibyte
,pebibytes
E
,e
,Ei
,EiB
,exbibyte
,exbibytes
Z
,z
,Zi
,ZiB
,zebibyte
,zebibytes
Y
,y
,Yi
,YiB
,yobibyte
,yobibytes
§システムプロパティによる従来のオーバーライド
Javaシステムプロパティは、application.conf
ファイルおよびreference.conf
ファイルにある設定をオーバーライドします。これにより、コマンドラインで設定オプションを指定できます。たとえば、sbt -Dkey=value run
です。
注:PlayはテストのためにJVMをフォークするため、テストでコマンドラインオーバーライドを使用するには、テストで使用する前に
build.sbt
でTest / Keys.fork := false
を追加する必要があります。
このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。 ドキュメントのガイドラインを読んだ後、プルリクエストを自由に貢献してください。質問や共有するアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めましょう。