概要
プロパティファイルの値を@Value
アノテーションを使って代入するサンプルコードです。
この記事では扱っていませんが@ConfigurationProperties
アノテーションを使ったConfigurationクラスでも同じ結果が得られます。
- 配列形式の値をList型へ
- 配列形式の値をSet型へ
- キー/バリュー形式の値をMap型へ
- 日付形式の値をLocalDateTime型へ
- ファイルパス形式の値をPath型へ
- 文字列の値をenum型へ
環境
- Windows 10 Professional
- Java 1.8.0_144
- Spring-Boot 1.5.4
参考
- [Part IV. Spring Boot features / 24. Externalized Configuration] (https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html)
- [Interface Converter<S,T>] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/convert/converter/Converter.html)
- [Interface ConverterRegistry] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/convert/converter/ConverterRegistry.html)
- [Interface ConditionalConverter] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/convert/converter/ConditionalConverter.html)
- [Properties with Spring and Spring Boot] (http://www.baeldung.com/properties-with-spring)
配列形式の値をList型へ
数値型の配列を代入する
プロパティファイルでカンマ区切りの値を配列と呼ぶかは定かではないのですが、Spring Bootではカンマ区切りの値をコレクション型のフィールドへ代入することができます。
プロパティファイル
hoge.fuga = 100, 200, 300
もしくはプロパティ名に[0]
のように添え字を付けることで配列として定義できます。
hoge.fuga[0]= 100
hoge.fuga[1]= 200
hoge.fuga[2]= 300
yml形式の場合は値の前に-
を付けて定義します。
hoge:
fuga:
- 100
- 200
- 300
コード
@Value("${hoge.fuga}")
private List<Integer> fuga;
文字列型の配列を代入する
プロパティファイル
hoge.fuga = りんご, みかん, なし
hoge:
fuga:
- りんご
- みかん
- なし
コード
@Value("${hoge.fuga}")
private List<String> fuga;
配列形式の値をSet型へ
文字列型の配列を代入する
プロパティファイル
hoge.fuga = りんご, みかん, なし
ymlファイルの場合、配列をSet型フィールドへ代入できません。
下記のような配列を代入しようとすると例外がスローされます。
hoge:
fuga:
- りんご
- みかん
- なし
しかし、propertiesファイルと同様にカンマ区切りにした場合は代入することが可能です。
hoge:
fuga: りんご, みかん, なし
コード
Value("${hoge.fuga}")
private Set<String> fuga;
キー/バリュー形式の値をMap型へ
キーが文字列型のMapへ代入する
プロパティファイル
hoge.fuga.key1 = val1
hoge.fuga.key2 = val2
hoge:
fuga:
key1: val1
key2: val2
コード
@Value("${hoge.fuga}")
private Map<String, String> fuga;
キーが数値型のMapへ代入する
プロパティファイル
hoge.fuga.101 = 123456789
hoge.fuga.201 = 456789012
hoge:
fuga:
101: 123456789
201: 456789012
コード
@Value("${hoge.fuga}")
private Map<Integer, Long> fuga;
日付形式の値をLocalDateTime型へ
LocalDate / LocalDateTime型へ代入する場合は、設定クラスに下記のようなFormatterを実装しConversionServiceに登録します。
@Bean
public ConversionService conversionService() {
Set<FormatterRegistrar> registrars = new HashSet<>();
registrars.add(dateTimeFormatterRegistrar());
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
factory.setFormatterRegistrars(registrars);
factory.afterPropertiesSet();
return factory.getObject();
}
private FormatterRegistrar dateTimeFormatterRegistrar() {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setDateTimeFormatter(dateTimeFormatterFactory());
registrar.setUseIsoFormat(true);
return registrar;
}
// Formatterの実装
private DateTimeFormatter dateTimeFormatterFactory() {
DateTimeFormatterFactoryBean factory = new DateTimeFormatterFactoryBean();
factory.setPattern("yyyy-MM-dd HH:mm:ss");
factory.setTimeZone(TimeZone.getDefault());
factory.afterPropertiesSet();
return factory.getObject();
}
LocalDateTime型へ代入する
プロパティファイル
hoge.fuga = 2017-08-01 23:59:59
hoge:
fuga: 2017-08-01 23:59:59
コード
@Value("${hoge.fuga}")
private LocalDateTime fuga;
LocalDate型へ代入する
プロパティファイル
hoge.fuga = 2017-08-01
hoge:
fuga: 2017-08-01
コード
@Value("${hoge.fuga}")
private LocalDate fuga;
ファイルパス形式の値をPath型へ
コンバーターなどの実装は不要です。サンプルとして絶対パス、相対パスを挙げていますがこれらの扱いに違いはありません。
相対パスの値を代入する
プロパティファイル
プロパティファイルの場合、パス区切り文字をエスケープしないとエラーになります。(windows環境の場合、Unix/Linux環境は未確認です)
hoge.fuga = dir1\\fuga.txt
ymlの場合は、パス区切り文字のエスケープは不要です。
hoge:
fuga: dir1\fuga.txt
コード
@Value("${hoge.fuga}")
private Path fuga;
絶対パスの値を代入する
プロパティファイル
hoge.fuga = D:\\dir1\\dir2\\fuga.txt
hoge:
fuga: D:\dir1\dir2\fuga.txt
コード
@Value("${hoge.fuga}")
private Path path;
文字列の値をenum型へ
プロパティの値をenum型へ代入するサンプルです。
文字列から解決したenumを代入する
プロパティファイルに記述した文字列から対応するenumを解決して代入します。
コンバーターなどの実装は不要です。
プロパティファイル
hoge.fuga = Gold
hoge:
fuga: Gold
enum定義
public enum Material {
Bronze,
Sliver,
Gold
;
}
コード
Value("${hoge.fuga}")
private Material fuga;
列挙子のフィールド値から解決したenumを代入する
プロパティファイルに記述した列挙子のフィールド値(この例ではlabelというフィールド)から対応するenumを解決して代入します。
この場合は、設定クラスに下記のようなConverterを実装しConversionServiceに登録します。
@Bean
public ConversionService conversionService() {
Set<Converter<?, ?>> converters = new HashSet<>();
converters.add(new StringToMaterialConverter());
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
factory.setConverters(converters);
factory.afterPropertiesSet();
return factory.getObject();
}
import com.example.lib.constants.Material;
import org.springframework.core.convert.converter.Converter;
public class StringToMaterialConverter implements Converter<String, Material> {
@Override
public Material convert(String value) {
return Material.lookup(value);
}
}
プロパティファイル
hoge.fuga = 金
hoge:
fuga: 金
enum定義
public enum Material {
Bronze("銅"),
Sliver("銀"),
Gold("金")
;
Material(String label) {
this.label = label;
}
private String label;
public String getLabel() {
return this.label;
}
public static Material lookup(String label) {
return Arrays.stream(Material.values())
.filter(material -> material.getLabel().equals(label))
.findFirst().orElseThrow(() -> new RuntimeException("unknown label : " + label));
}
}
コード
Value("${hoge.fuga}")
private Material fuga;