SpringBoot读取指定yaml文件内容

前言

在项目启动时,需要读取一些业务上大量的配置文件,用来初始化数据或者配置设定值等,我们都知道使用SpringBoot的@ConfigurationProperties注解 + application.yml配置可以很方便的读取这些配置,并且映射成对象很方便的使用,但是这些配置文件比较多的时候,而且不希望与application.yml放在一起,那么用SpringBoot如何实现呢。

my-config.yml

my-config:
  key1: hello

方法1 导入配置文件

application.yml中可以导入这些配置文件,然后继续使用@ConfigurationProperties注解,这样做的好处是最简单的,而且还可以增加my-conf-profile.yml的文件,以达到根据profile切换配置文件的目的

application.yml

spring:
  config:
    import: my-config.yml

MyConfig.java

@Data
@Configuration
@ConfigurationProperties(prefix="my-config")
public class MyConfig {
	private String key1;
}

方法2 使用@PropertySource注解加载配置文件

MyConfig.java

@Data
@Configuration
@ConfigurationProperties(prefix="my-config")
@PropertySource(value = "classpath:my-config.yml", factory = YamlPropertySourceFactory.class)
public class MyConfig {
	private String key1;
}

由于@PropertySource注解默认只支持properties格式的配置文件,所以要自定义yaml文件读取方式:

YamlPropertySourceFactory.java

import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()).get(0);
    }
}

上面的方法中返回的PropertySource内部实际上是由一个展平的Map对象,并且无法修改,源码可参照OriginTrackedYamlLoader.java。如果要对读取后的内容再进一步编辑,可以使用YamlPropertiesFactoryBean读取成Properties的形式去操作:
YamlPropertySourceFactory.java

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(resource.getResource());
        Properties properties = yamlPropertiesFactoryBean.getObject();
        
        // 这里加入自定义的属性
        properties.put("description", resource.getResource().getDescription());
        return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
    }
}

以上的几个方法原理都是将属性文件读取到整个Spring容器中,然后通过 @ConfigurationProperties 注解使用一个对象去映射需要的属性而已,如果读取文件的内容存在相同的key,那么后面读取到的则会覆盖前面的。这时候可以通过手动绑定的方法将读取到的内容直接放到对象中。

方法3 使用YamlPropertySourceLoader + Binder进行手动绑定

以上方法都会将MyConfig对象注入到Spring容器中去,而且配置文件也会在上下文的环境中存在,如果不想放入容器或者想对绑定的过程做更定制化的处理(比如判断文件修改时间等),那么需要手动绑定,生成配置对象。

MyConfig.java

@Data
public class MyConfig {
	private String key1;
}

BindDemo.java

import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;

public class BindDemo {

	public MyConfig getMyConfig() throws IOException {
        Resource resource = new ClassPathResource("my-config.yml");

        // 查看文件最后修改时间
        FileTime lastModifiedTime = Files.getLastModifiedTime(resource.getFile().toPath());
        String format = lastModifiedTime.toInstant().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("my-config.yml last modified time: " + format);

        List<PropertySource<?>> load = new YamlPropertySourceLoader().load(resource.getFilename(), resource);
        Binder binder = new Binder(ConfigurationPropertySource.from(load.get(0)));
        BindResult<DicProperties> bind = binder.bind("my-config", DicProperties.class); // 这里是配置的前缀,如果没有前缀,则传空字符串
        return bind.get();
	}
}

当然,以上也可以使用 YamlPropertiesFactoryBean 来完成:
BindDemo.java

import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;

public class BindDemo {

	public MyConfig getMyConfig() throws IOException {
        Resource resource = new ClassPathResource("my-config.yml");

        // 查看文件最后修改时间
        FileTime lastModifiedTime = Files.getLastModifiedTime(resource.getFile().toPath());
        String format = lastModifiedTime.toInstant().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("my-config.yml last modified time: " + format);

        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(resource);
        Properties properties = yamlPropertiesFactoryBean.getObject();
     
        // 这里加入自定义的属性
        properties.put("description", resource.getResource().getDescription());
        
        Binder binder = new Binder(ConfigurationPropertySource.from(new PropertiesPropertySource("my-config", properties)));
        BindResult<DicProperties> bind = binder.bind("my-config", DicProperties.class); // 这里是配置的前缀,如果没有前缀,则传空字符串
        return bind.get();
	}
}
### Spring Boot 中通过 `@ConfigurationProperties` 注解读取 YAML 配置文件Spring Boot 应用程序中,可以利用 `@ConfigurationProperties` 注解来绑定配置文件中的属性到 Java Bean 中。以下是关于如何使用该注解从 YAML 文件读取配置的具体实现。 #### 1. 创建 YAML 配置文件 假设有一个名为 `application.yml` 的配置文件,其中包含如下内容: ```yaml app: name: MyApplication version: 1.0.0 config: timeout: 3000 retries: 5 ``` 此 YAML 文件定义了一个嵌套结构的配置项,包括应用名称、版本号以及一些额外的配置参数。 --- #### 2. 定义对应的 Java 类 为了将上述 YAML 配置映射到 Java 对象中,需创建一个 POJO 类,并标注上 `@ConfigurationProperties` 和 `@Component` 注解以便让 Spring 自动加载这些配置。 下面是一个示例类: ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "app") // 绑定前缀为 app 的配置项 public class AppConfig { private String name; private String version; private Config config; public static class Config { private int timeout; private int retries; // Getter and Setter methods public int getTimeout() { return this.timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } public int getRetries() { return this.retries; } public void setRetries(int retries) { this.retries = retries; } } // Getter and Setter methods public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getVersion() { return this.version; } public void setVersion(String version) { this.version = version; } public Config getConfig() { return this.config; } public void setConfig(Config config) { this.config = config; } } ``` 注意:内部类 `Config` 被用来表示嵌套的配置部分。每个字段都需要提供 getter 和 setter 方法以满足 `@ConfigurationProperties` 的需求[^2]。 --- #### 3. 启用 ConfigurationProperties 支持 默认情况下,Spring Boot 已经启用了对 `@ConfigurationProperties` 的支持。但如果项目中有自定义条件或禁用了某些自动配置,则可能需要显式启用它。可以在主应用程序类或其他配置类上添加以下注解: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; @SpringBootApplication @EnableConfigurationProperties(AppConfig.class) // 显式声明要使用的配置类 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` --- #### 4. 测试配置注入 最后,在某个服务组件中验证配置是否成功注入: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class AppService { @Autowired private AppConfig appConfig; public void displayAppInfo() { System.out.println("Application Name: " + appConfig.getName()); System.out.println("Application Version: " + appConfig.getVersion()); System.out.println("Timeout: " + appConfig.getConfig().getTimeout()); System.out.println("Retries: " + appConfig.getConfig().getRetries()); } } ``` 运行时会打印出 YAML 文件指定的相关值。 --- ### 总结 以上展示了如何借助 `@ConfigurationProperties` 将 YAML 配置文件内容映射至 Java Bean 中的过程。这种方法不仅提高了代码可维护性和清晰度,还减少了手动解析配置的工作量[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值