Spring Boot 入门之配置文件加载

本文详细介绍SpringBoot配置文件的使用方法,包括配置文件的格式、加载顺序、多环境配置及自定义配置位置等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

前言

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 的区别

  • properties:键值形式,格式要求不是很高,结构不清晰。
  • yml:树状结构,格式要求比较严格,结构清晰。

SpringBoot 的配置文件加载顺序

一个项目部署时,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 

properties 和 yml 共存

当 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 是文件后缀名。

以上如有不对,见谅。再会!

更多可参考:

https://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#boot-features-external-config-application-property-files

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值