本記事の内容
この記事では、
Spring BootのプロジェクトでYAML(YML)形式のプロパティファイルから値を取得する方法について解説しています。
記事を書く経緯
一般的に、ハードコーディングを避けるため、システム内で使用する値をプロパティファイルに記載して外部化する場面があるかと思います。
Java/SpringBootでは、自動生成されるapplication.propeties
をプロパティファイル(設定ファイル)として使っていましたが、JSON形式のように読めて可読性も高いため、YAML形式のプロパティファイルapplication.yml
を採用しました。
デフォルトのプロパティファイルとなるapplication.yml
の他に、メッセージを管理するプロパティファイルmessage.yml
も必要となり、これを作成したところ、設定値が取得できずに詰まったので今回記事にします。
前提条件
下記の前提条件で、Spring Bootのプロジェクトを作成済みとします。
使用技術 | バージョン |
---|---|
Spring Boot | 2.7.2 |
解説
YAML形式のプロパティファイルから値が取得できない原因
調査を行うと、
まず、デフォルトのプロパティファイルとなるapplication.yml
以外のファイルは、@PropertySource
アノテーションを使って明示的にロードさせる必要があるとわかりました。
しかし、公式ドキュメントなどを漁って調査したところ、yaml形式のファイルは、単純に@PropertySource
アノテーションのvalue属性に指定してもロードができないようです。
@PropertySource(value = "classpath:message.yml")
public class sampleClass {
// プロパティを使う処理
// =>値を読み込めない!
}
下記のドキュメントを読むと、その旨の記載があります。
yaml形式のプロパティファイルを読み込む方法
ではyaml形式のプロパティファイルは使えないのかというともちろんそうではありません。
yaml形式のプロパティファイルをロードするには、@PropertySource
のfactory
属性を利用して、YAMLファイルを処理するPropertySourceFactory
のカスタム実装を提供することでロードが可能になり、値を参照することができます。
簡単に説明すると、プロパティを参照したいクラスが、yamlファイルを読み込むことができるfactoryという仲介者に頼んで、代わりにロードしてもらうことで、プロパティを参照したいクラスはyaml形式のファイルを読み込めるようになるというイメージです。
実装
今回はこのプロパティファイルを例にしていきます。
やることとしては、このような流れです。
-
message.yml
にメッセージとなる値を定義 -
PropertySourceFactory
をカスタム実装 - プロパティ利用クラス
MessageUtil.java
で値を取得
message.ymlにメッセージとなる値を定義
message:
error:
E101: システムエラーが発生しました。
E102: システムエラーが発生しました。
PropertySourceFactoryのカスタム実装
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
/** Yamlファイルをプロパティファイルとして読み込むためのファクトリクラス */
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource)
throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
// YAML形式のリソースをjava.util.Properties オブジェクトに変換
Properties properties = factory.getObject();
// ラッパーであるPropertiesPropertySourceのインスタンスを返却し、解析されたプロパティを読み取れるようにする
return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
}
}
プロパティ利用クラスMessageUtil.java
で値を取得
今回はMapで受け取るサンプルです。
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import com.example.App.config.YamlPropertySourceFactory;
import lombok.Setter;
/** メッセージ取得を提供するUtilityクラス */
@Component
@ConfigurationProperties(prefix = "message")
@PropertySource(value = "classpath:message.yml", factory = YamlPropertySourceFactory.class)
public class MessageUtil {
@Setter
private Map<String, String> error;
/**
* エラーメッセージ取得
* @param code エラーコード
* @return メッセージ
*/
public String getErrMessage(String code) {
return this.error.get(code);
}
}
コンソールで確認
public class Main {
public static void main(String[] args) {
MessageUtil messageUtil = new MessageUtil();
System.out.println(messageUtil.getErrMessage("E101"));
}
}
実行結果
システムエラーが発生しました。
まとめ
-
applicaton.properties
たは、applicaton.yaml(applicaton.yml)
はデフォルトで読み込んでくれるが、別のプロパティファイルを自作した場合は、@PropertySource
でロードする必要がある。 - yaml形式のプロパティファイルは、
@PropertySource
のfactory
属性を利用することで値を参照できる。
参考
baeldung SpringBootのYAMLファイルを使用した@PropertySource
baeldung yaml形式での取得
機能別 プロパティの取得方法