技术交流:springboot优雅获取自定义yml文件内容值

本文介绍如何使用SpringBoot优雅地从自定义YAML文件中读取配置信息。通过示例展示如何利用@PropertySource和@Value注解来注入配置文件中的属性值,并提供了一个具体的代码案例。

springboot优雅获取自定义yml文件内容值

@PropertySource

功能:@PropertySource注解用于指定资源文件读取的位置,它不仅能读取properties文件,也能读取xml文件,并且通过YAML解析器,配合自定义PropertySourceFactory实现解析YAML文件。

源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {

	/**
	 * Indicate the name of this property source. If omitted, the {@link #factory}
	 * will generate a name based on the underlying resource (in the case of
	 * {@link org.springframework.core.io.support.DefaultPropertySourceFactory}:
	 * derived from the resource description through a corresponding name-less
	 * {@link org.springframework.core.io.support.ResourcePropertySource} constructor).
	 * @see org.springframework.core.env.PropertySource#getName()
	 * @see org.springframework.core.io.Resource#getDescription()
	 */
	String name() default "";

	/**
	 * Indicate the resource location(s) of the properties file to be loaded.
	 * <p>Both traditional and XML-based properties file formats are supported
	 * &mdash; for example, {@code "classpath:/com/myco/app.properties"}
	 * or {@code "file:/path/to/file.xml"}.
	 * <p>Resource location wildcards (e.g. *&#42;/*.properties) are not permitted;
	 * each location must evaluate to exactly one {@code .properties} or {@code .xml}
	 * resource.
	 * <p>${...} placeholders will be resolved against any/all property sources already
	 * registered with the {@code Environment}. See {@linkplain PropertySource above}
	 * for examples.
	 * <p>Each location will be added to the enclosing {@code Environment} as its own
	 * property source, and in the order declared.
	 */
	String[] value();

	/**
	 * Indicate if a failure to find a {@link #value property resource} should be
	 * ignored.
	 * <p>{@code true} is appropriate if the properties file is completely optional.
	 * <p>Default is {@code false}.
	 * @since 4.0
	 */
	boolean ignoreResourceNotFound() default false;

	/**
	 * A specific character encoding for the given resources, e.g. "UTF-8".
	 * @since 4.3
	 */
	String encoding() default "";

	/**
	 * Specify a custom {@link PropertySourceFactory}, if any.
	 * <p>By default, a default factory for standard resource files will be used.
	 * @since 4.3
	 * @see org.springframework.core.io.support.DefaultPropertySourceFactory
	 * @see org.springframework.core.io.support.ResourcePropertySource
	 */
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;

}

@Value

功能:该注解的作用是将我们配置文件的属性读出来,有@Value(“${}”)和@Value(“#{}”)两种方式。

源码:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {

	/**
	 * The actual value expression such as <code>#{systemProperties.myProp}</code>
	 * or property placeholder such as <code>${my.app.myProp}</code>.
	 */
	String value();

}

示例代码

思路: 将自定义的aliyun.yml配置文件信息获取到spring中,便于源站url替换成cdn站点,防止资源盗链。

  1. 配置aliyun.yml
aliyun:
	cdn:
		url: https://cdn.aliyun.com
		privateKey: aliyuncdnkey
  1. 创建ALiYunCdnConfig类
@Component
@Getter
@Setter
@PropertySource("classpath:aliyun.yml")
public class ALiYunCdnConfig {

    @Value("${aliyun.cdn.url}")
    private String url;

    @Value("${aliyun.cdn.privateKey}")
    private String privateKey;
    
}
  1. 测试获取

编写相应的controller,依赖注入该ALiYunCdnConfig,对需要的源站url进行操作后返回加密后的cdn。

<think>在Spring Boot应用中,通常使用`application.yml`或`application.properties`作为默认配置文件。如果需要导入自定义名称的YAML配置文件(如`custom-config.yml`),可以通过以下方式实现: ### 解决方案 1. **使用`@PropertySource`注解(不直接支持YAML)** 注意:Spring的`@PropertySource`默认不支持YAML格式,需要额外处理。 2. **使用`@ConfigurationPropertiesScan`(推荐)** 结合`@ConfigurationProperties`扫描指定路径,但需要配合自定义配置加载器。 3. **自定义`PropertySourcesPlaceholderConfigurer`** 通过编程方式加载YAML文件。 4. **使用`YamlPropertySourceLoader`(最佳实践)** 在配置类中手动加载YAML文件并添加到环境变量中。 ### 详细实现(推荐方法) #### 步骤1:创建自定义配置类 ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import org.springframework.core.io.support.ResourcePropertySource; import java.io.IOException; @Configuration public class CustomYamlConfig { // 自定义PropertySourceFactory以支持YAML public static class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { // 使用YamlPropertySourceLoader代替默认的Properties加载器 return new ResourcePropertySource(resource); } } } ``` #### 步骤2:使用`@PropertySource`配合自定义工厂 ```java import org.springframework.context.annotation.PropertySource; @Configuration @PropertySource( value = "classpath:custom-config.yml", factory = CustomYamlConfig.YamlPropertySourceFactory.class // 指定自定义工厂 ) public class AppConfig { // 配置类内容(可留空) } ``` ### 替代方案:通过启动类初始化 ```java import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.PropertySource; import org.springframework.core.io.ClassPathResource; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.io.IOException; @SpringBootApplication public class Application { public static void main(String[] args) throws IOException { ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); // 手动加载YAML YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); PropertySource<?> propertySource = loader.load( "customConfig", new ClassPathResource("custom-config.yml") ).get(0); context.getEnvironment().getPropertySources().addLast(propertySource); } } ``` ### 原理说明 - **YAML解析机制**:Spring Boot默认通过`YamlPropertySourceLoader`处理YAML,但`@PropertySource`底层使用`PropertiesPropertySourceLoader`(仅支持properties)。因此需要扩展实现。 - **配置加载顺序**:自定义配置在`application.yml`之后加载,优先级低于默认配置(可通过`addFirst`提升优先级)。 ### 注意事项 - 确保文件路径正确:`classpath:`对应`resources`目录 - 若使用Spring Boot 3.0+,需确认依赖包含`spring-boot-starter` §§相关问题§§: 1. 如何在Spring Boot中同时加载多个自定义YAML文件? 2. `@PropertySource`注解为什么不支持直接加载YAML文件? 3. 如何指定自定义配置文件的加载顺序? 4. 在Spring Boot中,如何实现动态加载外部YAML配置文件? </think>在Spring Boot 3中,导入自定义YAML配置文件可以通过以下几种方式实现。Spring Boot默认使用`application.yml`作为主配置文件,但可以通过以下方法加载额外的YAML文件: ### 方法1:使用`@PropertySource` + 自定义工厂(推荐) 需要自定义PropertySourceFactory来支持YAML格式,因为Spring的`@PropertySource`默认只支持properties文件。 ```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; import org.springframework.lang.Nullable; import java.io.IOException; // 自定义YAML属性源工厂 public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public org.springframework.core.env.PropertySource<?> createPropertySource( @Nullable String name, EncodedResource resource) throws IOException { // 使用Spring Boot的YamlPropertySourceLoader加载YAML return new YamlPropertySourceLoader().load( resource.getResource().getFilename(), resource.getResource() ).get(0); } } ``` ```java import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @Configuration // 导入自定义YAML文件 @PropertySource( value = "classpath:custom-config.yml", factory = YamlPropertySourceFactory.class // 使用自定义工厂 ) public class CustomYamlConfig { // 配置类内容 } ``` ### 方法2:使用`spring.config.import`(Spring Boot 2.4+) 在`application.yml`中直接导入其他YAML文件: ```yaml # application.yml spring: config: import: - classpath:custom-config.yml - file:/path/to/external-config.yml ``` ### 方法3:编程式加载(灵活控制) 在启动类或配置类中通过代码加载: ```java import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.PropertySource; import org.springframework.core.io.ClassPathResource; import java.io.IOException; public class CustomYamlInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext context) { try { // 加载YAML文件 YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); PropertySource<?> propertySource = loader.load( "customConfig", new ClassPathResource("custom-config.yml") ).get(0); // 添加到环境变量 context.getEnvironment().getPropertySources() .addLast(propertySource); } catch (IOException e) { throw new RuntimeException("Failed to load YAML configuration", e); } } } ``` 注册初始化器: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MyApplication.class); application.addInitializers(new CustomYamlInitializer()); application.run(args); } } ``` ### 使用自定义配置 加载后,可以使用`@Value`或`@ConfigurationProperties`访问配置: ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "custom") public class CustomProperties { private String apiKey; private int timeout; private List<String> servers = new ArrayList<>(); // Getter和Setter // ... } ``` ```yaml # custom-config.yml custom: api-key: "a1b2c3d4e5" timeout: 5000 servers: - "server1.example.com" - "server2.example.com" ``` ### 关键注意事项 1. **加载顺序**:后加载的配置会覆盖先加载的配置 2. **文件路径**: - `classpath:`前缀:从类路径加载(src/main/resources) - `file:`前缀:从文件系统绝对路径加载 3. **Spring Boot 3兼容性**:以上方法均适用于Spring Boot 3.x 4. **配置文件优先级**:按照以下顺序加载(后面的覆盖前面的): 1. 打包在应用内的配置文件 2. 打包在应用内特定profile的配置文件 3. 外部配置文件 4. 外部特定profile的配置文件
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值