Springboot读取配置文件

指定配置文件

通常情况下我们将配置配置在application开头的主配置文件中,这样随着项目的增大配置项的增多会使文件变得非常臃肿,其实SpringBoot早已考虑到了该问题,SpringBoot提供了@PropertySource和@ImportResource两个注解用于加载外部配置文件使用。

  • @PropertySource通常用于属性加载配置文件,注意@PropertySource注解不支持加载yaml文件,支持properties文件。另外该注解只对加了的类生效,且application系列是全局属性,不需要单独指出
  • @ImportResource通常用于加载Spring的xml配置文件

@PropertySource使用

支持从classpath, file (本地), http 来获取配置

@PropertySource(value = {"classpath:config/user.properties"})
@PropertySource(value = {"classpath*:config/user.properties"})
@PropertySource(value = {"file:${user.home}/config/user.properties"})
@PropertySource(value = {"http://lwohvye/config/user.properties"}) //支持https

装配properties配置文件

在sources/config下创建一个yaml文件命名为user.properties内容与上方user的配置一样

Login类可如下写法

@PropertySource(value = {"classpath:config/user.properties"})
@Component
@ConfigurationProperties(prefix = "user")
public class Login{
    private String username;
    private String password;
    ...
}

运行一下,同样能达到加载配置效果

当需要根据不同的env读不同的file时,也可以实现

@PropertySource("classpath:/common-${spring.profiles.active}.properties")

但,这里spring.profiles.active不能配置多个(这个很好理解吧)

同时加载多个配置问题
细心的你,会发现@PropertySource注解中属性value为一个数组,如果同时加载多个配置文件,并且不同配置文件中对同一个属性设置了不同的值,那么Spring会识别哪一个呢?
带着疑问,我们可以通过控制变量法进行测试,具体过程再在赘述。

@PropertySource(value = {"classpath:config/user1.properties","classpath:config/user2.properties"})

结论:Spring加载顺序为从左到右顺序加载,后加载的会覆盖先加载的属性值。

装配yaml配置文件

如果你有强迫症,一定想加载yaml配置文件,那么可以通过PropertySourcesPlaceholderConfigurer类来加载yaml文件,将原来的user.properties改成user.yaml,Bean配置类中加入如下代码,Login配置类和一开始的方式一致。

@Bean
public static PropertySourcesPlaceholderConfigurer loadProperties() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
    //yaml.setResources(new FileSystemResource("classpath:config/user.yml"));//File路径引入
    yaml.setResources(new ClassPathResource("config/user.yml"));//class路径引入
    configurer.setProperties(yaml.getObject());
    return configurer;
}

运行一下,仍然可以能达到加载配置效果的

@ImportResource使用

SpringBoot提出零xml的配置,因此SpringBoot默认情况下时不会识别项目中Spring的xml配置文件。为了能够加载xml的配置文件,SpringBoot提供了@ImportResource注解该注解可以加载Spring的xml配置文件,通常加于启动类上。

@ImportResource(value = {"classpath:/beans.xml"})
@SpringBootApplication(scanBasePackages = {"team.seagull.client"})
public class DeployApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeployApplication.class, args);
    }
}

also see: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources, include Java properties files, YAML files, environment variables, and command-line arguments.

Property values can be injected directly into your beans by using the @Value annotation, accessed through Spring’s Environment abstraction, or be bound to structured objects through @ConfigurationProperties.

Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Later property sources can override the values defined in earlier ones. Sources are considered in the following order:

  1. Default properties (specified by setting SpringApplication.setDefaultProperties).
  2. @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
  3. Config data (such as application.properties files).
  4. RandomValuePropertySource that has properties only in random.*.
  5. OS environment variables.
  6. Java System properties (System.getProperties()).
  7. JNDI attributes from java:comp/env.
  8. ServletContext init parameters.
  9. ServletConfig init parameters.
  10. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
  11. Command line arguments.
  12. properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
  13. @TestPropertySource annotations on your tests.
  14. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.

Config data files are considered in the following order:

  1. Application properties packaged inside your jar (application.properties and YAML variants).
  2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
  3. Application properties outside of your packaged jar (application.properties and YAML variants).
  4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
It is recommended to stick with one format for your entire application. If you have configuration files with both .properties and .yml format in the same location, .properties takes precedence.

使用SpringCloudConfig

当@PropertySource和ControlConfig配合时,

  • 如果要load的file需要从ConfigServer获取,则不需要使用@PropertySource指定,再配置 spring.cloud.config.name和spring.cloud.config.profile后 会自动从远程获取所有需要的配置并bind,如果配置@PropertySource(“classpath:remoteFileName”),因为本地没有,会报fileNotFound,可以配置 ignoreResourceNotFound = true 忽略异常
  • 如果本地和远程有两个同名的配置文件,则整个本地的配置文件会被ignore,注意不是覆盖,而是ignore整个file
  • 如果本地和远程有相同的配置项,则远程会覆盖本地(这个容易理解,可以简单理解为拿到所有属性然后bind,先加载本地再加载从远程获取的,自然后面的会覆盖前面的)
  • 使用@PripertySource配置的文件,不支持refresh(改本地不会refresh,同名按远程为准所以可以refresh远程的update),但这不能算问题,需要refresh可以走ConfigServer

读取远程配置

https://stackoverflow.com/questions/25271537/remote-propertysource

Leave a Reply

Your email address will not be published. Required fields are marked *

lWoHvYe 无悔,专一