Spring Boot 入门之配置文件加载
文章目录前言Spring Boot 配置文件概述简介配置文件名称、格式properties 和 yml 的区别SpringBoot 的配置文件加载顺序多配置文件加载特性多环境配置properties 和 yml 共存任意位置加载ApplicationEnvironmentPreparedEvent 事件之重置配置文件加载位置扩展前言Spring Boot 在工作
文章目录
前言
Spring Boot 在工作中是用到的越来越广泛了,简单方便,有了它,效率提高不知道多少倍。Spring Boot 配置文件对 Spring Boot 来说就是入门和基础,经常会用到。下面话不多说了,来一起看看详细的介绍吧。
Spring Boot 配置文件概述
当我们新建一个 Springboot 项目之后,会在 resources 目录下给我们一个默认的全局配置文件 application.properties,这是一个空文件,因为 Spring Boot 在底层已经把配置都给我们自动配置好了,当在配置文件进行配置时,会修改 SpringBoot 自动配置的默认值。
配置文件名是固定的 application.properties 或者 application.yml。当然有时候一个配置文件是不能满足我们的需求,我们可能会配置多个,这个时候我们可以修改后缀来区分不同的配置文件 ,比如 application-dev.properties。还可以通过 spring.config.name 来直接修改配置文件前缀名称。
- 配置文件格式:
application-{profile}.properties/yml - 自定义名称可使用参数:
--spring.config.name=customname
- properties:键值形式,格式要求不是很高,结构不清晰。
- yml:树状结构,格式要求比较严格,结构清晰。
一个项目部署时,SpringBoot 的配置文件应该放在哪?加载顺序是什么呢?
工程根目录:./config/
工程根目录:./
classpath:/config/
classpath:/
注:application-profile 优先于 application。
优先级顺序是从上向下加载(优先级从高到低),所有的文件都会被加载,高优先级的内容会覆盖低优先级的内容,形成互补配置。
多配置文件加载特性
正常的开发中会有多个环境,测试环境,开发环境,生产环境等。无论采用 properties 还是 yml,都可以根据不同的使用环境来指定使用具体环境的配置文件。各环境配置文件名称 application-{profile}.properties/yml,即前面提到的。举例:
- application-dev.properties:开发环境配置文件
- application-test.properties:测试环境配置文件
- application-pro.properties:生产环境配置文件
如果这三个都放在项目下,那我们如何判断各个环境应该加载哪个配置文件呢,这时我们便可以用如下参数来按需加载。
--spring.profiles.active=dev
当 application.properties 和 yml 文件在并存时(同一目录下),application.properties 优先级更好,会先读它,若它没有,再去读 yml 中的值。
当配置文件和项目部署路径不一致时,可通过参数来指定配置文件位置。
--spring.config.location=path
ApplicationEnvironmentPreparedEvent 事件之重置配置文件加载位置
问题一:现在有一种需求,一个项目配置项很多,不过可以拆分为两类,一类是程序默认配置一般不需要改动,一类是用户自定义配置。那这个时候我们怎么办呢?而且一般程序都是交由实施去部署的,而实施对 yml 格式把握不是很好,部署时很容易出现错误而且很难发现。导致程序起不来让人头疼,这又怎么解决呢?
解决:我们是否可以用上面所说的 yml 和 properties 同时配置呢?yml 对程序员来说比较符合书写规范,properties 对实施人员来说比较容易上手,没有特别的格式要求,即使多一个空格也无足轻重。而 yml 却不同。
于是有了我们的设计方案,程序配置分为两类,application.yml 和 application.properties。yml 里面是程序默认配置,pro 里面是自定义的配置。前面也说到这两个是可以共存的,而且是互补配置,也就是说 properties 里面配置自定义参数的可以覆盖 yml 里面的同名键的默认配置。这样就解决了这个问题。
问题二: 这里还有一个问题,当两个文件放在程序下的同一个位置,比如 classpath:/config/ 下,那加载自然是没问题的,要是我这个自定义的 application.properties 不想放在程序里面,而想放在服务器上的任意一个位置呢,这怎么解决?
你肯定会想到用 --spring.config.location 来加载。但是如果你写了这个参数,SpringBoot 是加载不到默认的 yml 配置文件的。当然我们也可以用 --spring.config.location 把自定义和程序默认的位置都一起指定。比如:
--spring.config.location=/opt/work/tomcat8/webapps/application.properties,classpath:/config/application.yml
这样也是可以同时加载这里个配置文件的。
但是路径太长了,我们不想配置,那就得去看下源码了。


可以看到这里其实所有的配置文件路径最终会被存到一个 Set 里面,这里有顺序的问题,路径会被逆转顺序。也就是说配置在前面的优先级低。这是需要注意的。

看到这,我们是否可以监听一个事件,去改变这个 spring.configs.location 的值呢,毕竟 yml 在程序包中的位置一直是固定的,我不想每次都配置。是有的,就是 ApplicationEnvironmentPreparedEvent。话不多说,直接上代码吧。
/**
* 重置配置文件加载位置
* 这里为啥有两个 reset 方法呢,因为我们配置 spring.config.location 有两种方式,
* 一种配置 program 参数 --spring.config.location=path
* 另外一种配置 vm 参数:-Dspring.config.location=path
*
*/
@Component
public class CustomConfigApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>,Ordered {
private static Logger logger=LoggerFactory.getLogger(CustomConfigApplicationListener.class);
private static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE +9;
private static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
ConfigurableEnvironment envi = event.getEnvironment();
MutablePropertySources prpoSource = envi.getPropertySources();
StringBuffer config = new StringBuffer("--");
config.append(CONFIG_LOCATION_PROPERTY);
config.append("=classpath:\\config\\");
resetCommonLineArgs(prpoSource, config);
resetSystemProperties(prpoSource, config);
}
}
private void resetCommonLineArgs(MutablePropertySources propSource, StringBuffer config) {
PropertySource<?> commandLineArgs = propSource.get("commandLineArgs");
if (null != commandLineArgs) {
String defaultLocation = commandLineArgs.getProperty(CONFIG_LOCATION_PROPERTY) != null
? (String) commandLineArgs.getProperty(CONFIG_LOCATION_PROPERTY)
: null;
if (null != defaultLocation) {
config.append(",");
config.append(defaultLocation);
logger.info("加载配置文件:"+config.toString().substring(config.indexOf("=")+1));
PropertySource<?> newEnv = new SimpleCommandLinePropertySource(config.toString());
propSource.addFirst(newEnv);
}
}
}
@SuppressWarnings("unchecked")
private void resetSystemProperties(MutablePropertySources propSource, StringBuffer config) {
PropertySource<?> systemProperties = propSource.get("systemProperties");
if (null != systemProperties) {
Map<String, Object> pro = (Map<String, Object>) systemProperties.getSource();
String defaultConfig = pro.get(CONFIG_LOCATION_PROPERTY) != null
? (String) pro.get(CONFIG_LOCATION_PROPERTY)
: null;
if (null != defaultConfig) {
config.append(",");
config.append(defaultConfig);
pro.put(CONFIG_LOCATION_PROPERTY, config.substring(config.indexOf("=")+1).toString());
logger.info("加载配置文件:"+defaultConfig);
MapPropertySource mapPropertySource = new MapPropertySource("systemProperties", pro);
propSource.addBefore("systemEnvironment", mapPropertySource);
}
}
}
@Override
public int getOrder() {
return DEFAULT_ORDER;
}
}
这样我们就实现了配置文件同时加载 yml 和 properties,并且 properties 可以放在任意位置。可以直接在 tomcat 中配置文件位置。
扩展
当需要配置多个自定义文件时,可以使用如下参数在主配置文件中引入其他配置文件:
--spring.profiles.include=redis,mysql
这里的 redis 和 mysql 是文件后缀名。
以上如有不对,见谅。再会!
更多可参考:
更多推荐



所有评论(0)