網頁

2020/10/1

Spring Boot @PropertySource load yaml

Spring Boot @PropertySource預設只載入properties檔,如果想要用yaml來配置則要修改以下。

範例環境:

  • Java 8
  • Spring Boot 2.3.2.RELEASE
  • Maven
  • Lombok

範例專案src/main/reosurce classpath有自訂配置檔system.yamlsystem.properties內容如下。

system.yaml

system:
  name: Demo system
  version: 1.0.0

system.properties

system.url=192.168.0.111
system.port=8080

在配置類設定@PropertySourcevalue指定system.yamlsystem.properties為properties來源,並將factory屬性指定為自訂的PropertySourceFactory,也就是下面的YamlPropertySourceFactory

DemoApplication

package com.abc.demo;

import com.abc.demo.confg.factory.YamlPropertySourceFactory;
import com.abc.demo.properties.SystemProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;

@EnableConfigurationProperties(SystemProperties.class)
@PropertySource(
        value = {
                "classpath:system.yaml",
                "classpath:system.properties"
        },
        factory = YamlPropertySourceFactory.class // <-- 指定為自訂的PropertySourceFactory類別
)
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {

        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        SystemProperties systemProperties = ctx.getBean(SystemProperties.class);

        System.out.println(systemProperties.getName());    // Demo system
        System.out.println(systemProperties.getVersion()); // 1.0.0
        System.out.println(systemProperties.getUrl());     // 192.168.0.111
        System.out.println(systemProperties.getPort());    // 8080

    }

}

新增YamlPropertySourceFactory並實作PropertySourceFactory並覆寫createPropertySource(),以YamlPropertiesFactoryBeanResource轉為Properties後作為建構PropertiesPropertySource的參數並回傳,此為讀取yaml為properties的程式。

YamlPropertySourceFactory

package com.abc.demo.confg.factory;

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.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

import java.io.IOException;
import java.util.Properties;

public class YamlPropertySourceFactory implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {

        String resourceFileName = resource.getResource().getFilename(); // e.g. system.yaml, system.properties

        if (resourceFileName == null || resourceFileName.length() == 0) {
            return new DefaultPropertySourceFactory().createPropertySource(name, resource);
        }

        if (resourceFileName.endsWith("yaml") || resourceFileName.endsWith("yml")) {
            YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
            factoryBean.setResources(resource.getResource());
            Properties properties = factoryBean.getObject();

            return new PropertiesPropertySource(resourceFileName, properties);
        }

        if (resourceFileName.endsWith(".properties")) {
            return new DefaultPropertySourceFactory().createPropertySource(resourceFileName, resource);
        }

        return new DefaultPropertySourceFactory().createPropertySource(name, resource);
    }
}

SystemProperties@ConfigurationProperties綁定properties的bean。

SystemProperties

package com.abc.demo.properties;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Getter
@Setter
@ConfigurationProperties(prefix = "system")
public class SystemProperties {

    private String name;    // system.name (system.yaml)
    private String version; // system.version (system.yaml)
    private String url;     // system.url (system.properties)
    private String port;    // system.port (system.properties)

}

啟動後印出結果如下。

Demo system
1.0.0
192.168.0.111
8080

參考github


沒有留言:

張貼留言