Spring Boot起動時に環境毎の設定ファイルを利用する方法 3パターン
Spring Boot × Gradleで起動時に読み込む設定ファイルを切り替える方法を3種類記載します。
方法の概説
- spring.profile.activeで起動時のapplication.yml (application.properties) を指定
- build時に環境毎の設定ファイルディレクトリをclass pathに追加
- 起動時にclass pathを追加
システム構成は以下リンクを参照ください。 ただし1, 2についてはマルチプロジェクト構成である必要はなく、env層も不要です。
1.spring.profiles.activeで起動時のapplication.yml (application.properties) を指定
spring.profiles.activeで起動時の設定ファイルを指定する方法です。 IDEでの起動時にはdefaultになります。 application.ymlで設定が完結している場合、この方法が一番シンプルです。
構成
└── src ├── main │ └── resources │ ├── application-common.yml │ ├── application-development.yml │ ├── application-local.yml │ ├── application.yml │ └── mybatis │ └── sql │ ├── mysql
application.yml
spring.profiles: default spring.profiles.active: default spring.profiles.include: - development - local # 最後に置いたもので設定を上書きする
application-development.yml
spring.profiles: development spring.profiles.include: - common spring: datasource: # 以下、datasourceの設定... # Logger設定 logging: level: org.springframework.web.servlet.PageNotFound: ERROR org.springframework.transaction: INFO
application-common.yml
# 環境に依存しない共通設定を記載する場所
application-local.yml
# 個人の開発で利用する場所 logging: level: org.springframework.transaction: TRACE
IDEでの起動時はapplication.ymlが利用されます。今回の例ではtransactionのlogging levelがTRACEになります。
application-development.ymlで起動する場合は、executable jarの起動時に以下のように指定すればOK。
java -Dspring.profiles.active=development -jar demo-web-0.0.1-SNAPSHOT.jar
2.build時に環境毎の設定ファイルディレクトリをclass pathに追加
設定ファイルが複数の場合、gradle build時にclass pathを追加する方法が有効です。
構成
└── src ├── main │ └── resources │ ├── application-common.yml │ ├── application-development.yml │ ├── application-local.yml │ └── mybatis │ └── sql └── profile ├── development │ └── application.yml └── local └── application.yml
src直下にprofile directoryを用意して、配下にapplication.ymlを置きます。 その他、環境に依存する設定があればprofileに追加していきます。環境に依存しないSQLファイルなどはsrc/main/resourcesに置きます。
development/application.yml
spring.profiles.active: development
local/application.yml
spring.profiles: default spring.profiles.active: default spring.profiles.include: - development - local # 最後に上書きしたものが有効になる
起動時にclass pathが追加になるようにbuild.gradleに設定します。
subprojects { // ...前略 sourceSets { // profileごとのresourceを追加 def envProfile = project.hasProperty('env_profile') ? project.properties['env_profile'] : 'local' main.resources { srcDirs "src/profile/$envProfile" } } // 後略... }
デフォルト起動時はprofile/local が採用されます。build時にpathを変える場合はgradleのPオプションを使用します。
./gradlew bootJar -Penv_profile=development
あとは普通にexecutable jarを起動すればOK
3. 起動時にclass pathを追加
build時に設定ファイルをexecutable jarから外しておき、起動時に外部class pathに追加します。
構成
└── src ├── main │ └── resources │ ├── application.yml │ └── mybatis │ └── sql └── profile ├── development │ └── application.yml
この方法の場合、設定ファイルは独立したprojectに用意する必要があります。env層を用意して、設定ファイルはすべてここに置きます。 デフォルトではsrc/main/resources/application.ymlが読まれます。
executable jarにenv層を取り込まないようにし、またPropertiesLauncher
を入れて外部class pathを追加できるようにします。
demo-web/build.gradle
bootJar { mainClassName = 'com.example.demo.DemoApplicationKt' // daemon化する launchScript() // loader.propertiesでクラスパスを追加するためにPropertiesLauncherを使う manifest { attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher' } } // env層をjarから除去する configurations { runtime.exclude module: 'demo-env' }
src/profileのapplication.yml 等の設定ファイルを利用するために、release用のtaskを書きます
task release(dependsOn: ['demo-web:build']) { // build用ディレクトリ def applicationDir = new File(buildDir, 'application') doFirst { description 'build配下にapplication directoryを作成する' // 古いディレクトリが存在していたら削除 if (applicationDir.exists()) { delete(applicationDir) } // build用directory作成 applicationDir.mkdirs() } doLast { // demo-webで作成したjarファイルをapplicationDirにcopyする description 'application directoryにdemo-webのjarファイルをcopyする' project(':demo-web') { copy { from "${buildDir}/libs" into applicationDir include("*.jar") } } } doLast { description 'application directoryにdemo-envのresourceファイルをcopyする' // demo/build/application/resources def applicationResourcesDir = new File(applicationDir, 'resources') // develop / staging / production など環境を取得 // -P optionだとproject.getProperty, -D optionだとSystem.getProperty def envProfile = project.hasProperty("env_profile") ? project.properties["env_profile"] : 'local' println("build profile is ${envProfile}") project(':demo-env') { copy { from "${projectDir}/src/main/resources" into applicationResourcesDir } // envのprofileで上書きをする if (envProfile != 'local') { String profileDir = "${projectDir}/profile/${envProfile}" if (!file(profileDir).exists()) { throw new GradleException(profileDir + " is not found") } copy { from "${projectDir}/profile/${envProfile}" into applicationResourcesDir } } } } }
profile 以下のファイルでsrc/main/resourcesのファイルを上書きコピーしています。
build時にはprofileを指定します。
./gradlew -Penv_profile=development release
demo/build以下にapplication directoryができて、その下にresourcesとexecutable jarができます。
├── application │ ├── demo-web-0.0.1-SNAPSHOT.jar │ └── resources
起動時にloader.path=resources
を指定して、class path にresourcesを追加します。
java -Dloader.path=resources -jar demo-web-0.0.1-SNAPSHOT.jar
手間のかかる方法ですが、build後にresourceファイルを修正できる利点があります。
まとめ
gradleを利用した環境毎の設定ファイル読み込み方法をまとめました。
個人的には1 > 2 > 3の順でおすすめです。
(しかし会社で採用している方法は3だったりします ;-))