5
2

More than 1 year has passed since last update.

【Java・Spring Boot】YAML形式のプロパティファイルから値を取得する方法

Posted at

本記事の内容

この記事では、
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属性に指定してもロードができないようです。

NGパターン
@PropertySource(value = "classpath:message.yml")
public class sampleClass {
  // プロパティを使う処理
  // =>値を読み込めない!
}

下記のドキュメントを読むと、その旨の記載があります。

yaml形式のプロパティファイルを読み込む方法

ではyaml形式のプロパティファイルは使えないのかというともちろんそうではありません。
yaml形式のプロパティファイルをロードするには、@PropertySourcefactory属性を利用して、YAMLファイルを処理するPropertySourceFactoryのカスタム実装を提供することでロードが可能になり、値を参照することができます。

簡単に説明すると、プロパティを参照したいクラスが、yamlファイルを読み込むことができるfactoryという仲介者に頼んで、代わりにロードしてもらうことで、プロパティを参照したいクラスはyaml形式のファイルを読み込めるようになるというイメージです。

実装

今回はこのプロパティファイルを例にしていきます。
やることとしては、このような流れです。

  • message.ymlにメッセージとなる値を定義
  • PropertySourceFactoryをカスタム実装
  • プロパティ利用クラスMessageUtil.javaで値を取得

message.ymlにメッセージとなる値を定義

message.yml
message:
  error:
    E101: システムエラーが発生しました。
    E102: システムエラーが発生しました。

PropertySourceFactoryのカスタム実装

YamlPropertySourceFactory.java
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で受け取るサンプルです。

MessageUtil.java
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);
  }
}

コンソールで確認

Main.java

public class Main {

  public static void main(String[] args) {
    MessageUtil messageUtil = new MessageUtil();
    System.out.println(messageUtil.getErrMessage("E101"));
  }
}

実行結果

console
システムエラーが発生しました。

まとめ

  • applicaton.propertiesたは、applicaton.yaml(applicaton.yml)はデフォルトで読み込んでくれるが、別のプロパティファイルを自作した場合は、@PropertySourceでロードする必要がある。
  • yaml形式のプロパティファイルは、@PropertySourcefactory属性を利用することで値を参照できる。

参考

baeldung SpringBootのYAMLファイルを使用した@PropertySource
baeldung yaml形式での取得
機能別 プロパティの取得方法

関連記事

開発・本番用 環境別に取得する方法

5
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2