1. 项目内部配置文件
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。
SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在—互补配置。
对于Spring Boot项目加载外部配置文件,有两种做法可以实现该目的:
1.1. --spring.config.location
--spring.config.location="D:/xxx/system.properties"
要特别注意的是,该命令指定的配置文件会使项目默认的application.properties或application.yml文件失效,换句话说该命令会用指定的配置文件替换application.properties或application.yml文件。
java -jar spring-boot-SNAPSHOT.jar --spring.config.location=file:///D:/application.properties,classpath:/,classpath:/config/
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置。
指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。
Idea 单测启用自定义配置:添加jvm参数:-Dspring.config.location=file:///D:/project_conf/application.yml -ea
1.2. --spring.config.additional-location
--spring.config.additional-location="D:/xxx/system.properties"
顾名思义,该命令用于追加配置文件。原有的application.properties或application.yml文件均有效。
Spring提供了profiles的概念可以帮助我们进行多环境的配置,首先看下类ConfigFileApplicationListener的getSearchLocations
// Note the order is from least to most specific (last one wins)
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
public static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";
public static final String CONFIG_ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location";
private Set<String> getSearchLocations() {
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
return getSearchLocations(CONFIG_LOCATION_PROPERTY);
}
Set<String> locations = getSearchLocations(
CONFIG_ADDITIONAL_LOCATION_PROPERTY);
locations.addAll(
asResolvedSet(ConfigFileApplicationListener.this.searchLocations,
DEFAULT_SEARCH_LOCATIONS));
return locations;
}
从上述代码可以看出,如果有在Environment中指定了 spring.config.location 会只取该项的地址去获取配置文件,若没有指定spring.config.location,配置文件获取优先级为
1. spring.config.additional-location指定的地址
2. file:./config/
3. file:./
4. classpath:/config/
5. classpath:/
而spring.config.name、spring.config.location和spring.config.additional-location等配置是从environment中获取的,详情可跳转 Spring Boot官方参考了解更多信息 Application Property Files
上述可以得出,只要在environment(环境变量) 中指定不同的spring.config.additional-location就可以达到war包与配置文件分离的效果,常见形式如下
- jar包:jar spring-boot-sample-web.jar –spring.config.additional-location=~/config/
- war包:在tomcat中可以在${TOMCAT_HOME}/conf/catalina.properties末尾添加
#spring environment property
spring.config.additional-location=~/config/#配置文件所在文件夹
注意:file:./ 在打成jar包的springboot项目指向jar包所在目录,以war包形式在tomcat中指向startup所在的bin目录,具体可在不同环境中输出 file:./ 对应的绝对路径
new DefaultResourceLoader().getResource(“file:./”).getFile().getAbsolutePath();
1.3.文件名问题
对于application.properties而言,它不一定非要叫application,但是项目默认去加载名为application的配置文件,如果我们的配置文件不叫application,也是可以的,但是需要明确指定配置文件的文件名。
方式和指定路径一致,只不过此时key是spring.config.name.
例:首先在resource目录下创建一个app.properties文件,然后再启动配置参数 --spring.config.name=app
2. 外部配置加载顺序
SpringBoot也可以从以下位置加载配置:优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。
1.命令行参数
- 所有的配置都可以在命令行上进行指定;
- 多个配置用空格分开; –配置项=值
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
2.来自java:comp/env的JNDI属性
3.Java系统属性(System.getProperties())
4.操作系统环境变量
5.RandomValuePropertySource配置的random.*属性值
6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
10.@Configuration注解类上的@PropertySource ,(yaml文件不支持@PropertySource
@Configuration
@PropertySource(value = {"file:/xxx/xxx/config/xxxConfig.properties"}, encoding = "utf-8")
11.通过SpringApplication.setDefaultProperties指定的默认属性
3.war包部署读取外部配置.yml文件的方法
当我们使用springboot开发时,有的时候需要打war包在外部tomcat部署,方便运维人员维护,但是修改配置文件后重新打包给运维的时候,又需要修改一些配置这样还是不方便维护。
在网上找了很多例子但是都是针对.properties文件,读取.yml文件会有问题,当我在看关于springboot加载yml文件时发现需要用到其他的类,YamlPropertiesFactoryBean和YamlMapFactoryBean。下面把读取外部.yml配置文件的方法贴出来。
自定义配置类实现EnvironmentPostProcessor接口
- EnvironmentPostProcessor是springboot支持动态读取文件的接口,实现EnvironmentPostProcessor接口覆写postProcessEnvironment方法
- 在postProcessEnvironment方法实现读取外部配置文件
- 使用YamlPropertiesFactoryBean来读取yml配置文件,getObject()方法可以获取Properties
首先我把springboot.yml配置文件放在tomcat目录的conf目录下(可以根据自己需求修改目录)
实现EnvironmentPostProcessor在方法中完成yml配置读取
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
//tomcat路径
String property = System.getProperty("catalina.home");
String path = property + File.separator + "conf" + File.separator + "myapplication.yml";
//Springboot读取yml配置
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new FileSystemResource(path));
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(new PropertiesPropertySource("Config", yaml.getObject()));
}
}
在resouces目录下建一个META-INF文件目录,在目录中建一个spring.factories文件,在文件中配置自己实现的动态读取文件类
org.springframework.boot.env.EnvironmentPostProcessor=com.hzone.demo.config.MyEnvironmentPostProcessor
在pom.xml中配置maven打包时移除配置文件
最后tomcat启动,springboot启动会加载datasource配置创建'sqlSessionFactory',正序正常启动就说明这种方式读取yml配置文件没有问题。
正常启动,成功加载到了.yml配置文件。
最后说一下logback.xml配置文件丢到外面直接在.yml配置文件中配置好路径就可以了