Overview
spring bootの設定ファイルの保守性を上げる
- spring boot 2.7.0
- 設定ファイルはyml形式を使用
保守性をあげるために設定ファイルに求めること
- 環境に応じて切替可能
- ファイル分割(コンフリクトを避ける、設定がみつけやすい)
- 外部からの値の注入(シークレット情報を扱う場合は重要)
- 起動の簡単さ(必須設定が多すぎると新規開発者が苦労する)
Spring Bootの機能
基本
設定ファイルとそれを読み込むConfigクラスを準備。(@Valueでも同様に動くが今回は省略。)
src/main/resources/application.yml
myapp: configTest: key: value env_test: ${ENV_TEST} noenv: ${NO_ENV:default_value} flag: true env: no_env
ConfigTest.java
@Data @ConfigurationProperties(prefix = "myapp.config-test") @Component public class ConfigTest { private String key; private String key2 = null; private String envTest; private String noenv; private boolean flag; private String env; }
読み込みはAutowiredして呼びたい設定のgetterを呼べばOK。 (ここではテスト結果が見やすいようにtoString()を読んでます。)
@SpringBootApplication @Slf4j public class ConfigApplication implements CommandLineRunner { @Autowired private ConfigTest configTest; public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); System.exit(0); } @Override public void run(String... args) throws Exception { log.info(configTest.toString()); } }
実行ログ
2022-08-21 20:39:03.100 INFO 62961 --- [ main] c.y.dev.config.ConfigApplication : ConfigTest(key=value, key2=null, envTest=injected_value, noenv=default_value, flag=true, env=no_env)
profile
例
application.yml
,application-dev.yml
,application-prod.yml
を準備- dev環境:
export spring_profiles_active=dev
してからアプリ実行 ->application-dev.yml
が読まれる - prod環境:
export spring_profiles_active=prod
してからアプリ実行 ->application-prod.yml
が読まれる
src/main/resources/application-dev.yml
myapp: configTest: env: dev
環境変数spring_profiles_active=dev
を設定して実行ログ確認
2022-08-21 16:59:05.057 INFO 61874 --- [ main] c.y.dev.config.ConfigApplication : The following 1 profile is active: "dev" ... 2022-08-21 16:59:07.101 INFO 61874 --- [ main] c.y.dev.config.ConfigApplication : ConfigTest(key=overwritten_by_external, key2=null, envTest=injected_value, noenv=default_value, flag=true, env=dev)
env=dev
になっているのでうまく動作している。
参考 https://www.baeldung.com/spring-profiles https://spring.pleiades.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files.profile-specific
外部ファイル読み込み
src/main/resources/application.yml (追記)
spring: config: import: - "another.yml" - "optional:file:./spring-mvc/dev/external-config.yml"
src/main/resources/another.yml
myapp: configTest: key: overwritten_by_another
spring-mvc/dev/external-config.yml
myapp: configTest: key: overwritten_by_external
実行ログ
2022-08-21 16:59:07.101 INFO 61874 --- [ main] c.y.dev.config.ConfigApplication : ConfigTest(key=overwritten_by_external, key2=null, envTest=injected_value, noenv=default_value, flag=true, env=dev)
external-config.ymlが優先されるので値はkey=overwritten_by_external
となっている。
環境変数読み込み
「基本」の env_test: ${ENV_TEST}
を参照。${}
内で指定した環境変数が自動で展開される。このプレースホルダは設定ファイル内の他の値を展開したり文字列の結合したりも可能。
https://spring.pleiades.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files.property-placeholders
default値の設定
環境変数が設定されない場合
env_test: ${ENV_TEST:default-value}
のように書ける。
他の値はJava class側のコンストラクタで設定しておけばデフォルトを持てるが、設定ファイル側に入れておいたほうが見やすい。
ConfigTest.java
@Data @ConfigurationProperties(prefix = "myapp.config-test") @Component public class ConfigTest { private String key = "default-value"; ...
環境変数 vs profile
環境変数でもprofileでも環境ごとの値の設定は可能。 - 環境変数 - シークレットを扱いやすい - 値の変更が容易 - yamlのような構造がないのでリスト型や辞書型の設定は持ちづらい - profile - 構造があるので多数の設定やリスト型、辞書型の設定も扱いやすい - シークレットを使うなら結局プレースホルダーで環境変数を入れることになりそう - JARに設定ファイルを入れているなら値の変更に再度ビルドが必要 設定値が少ないうちは環境変数で環境差異を吸収するのが良さそう。
感想
Spring Bootの外部設定管理まわりは機能が多くて、同じことを複数のやり方でできることが多い。 何を使って何を使わないか決めておくのがよさそう。