一、前言
Spring Cloud
构建于 Spring Boot
之上,在 Spring Boot
中有两种上下文,一种是 bootstrap
,另外一种是 application
。
二、bootstrap与application (.yml/.properties)
2.1 两者区别
bootstrap.yml/bootstrap.properties
和 application.yml/application.yml
都可以用来配置参数。
-
bootstrap.yml/bootstrap.properties
:用来程序引导时执行,应用于更加早期配置信息读取。可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。 -
application.yml/application.yml
:可以用来定义应用级别的, 应用程序特有配置信息,可以用来配置后续各个模块中需使用的公共参数等。
文件名.properties /文件名.yml
文件名相同且同时存在时,先加载.properties
文件,再加载.yml
文件。
2.2 两者加载顺序
若application.yml/.properties
和 bootstrap.yml/.properties
在同一目录下:bootstrap
先加载,application
后加载
bootstrap.yml/.properties
用于创建初始化Bootstrap Context
。application.yml/.properties
用于创建初始化Application Context
。
bootstrap.yml/.properties
和 application.yml/.properties
共享同一个 Environment
。Environment
它是任何 Spring
应用程序的外部属性的来源。bootstrap.yml/.properties
属性以高优先级添加,因此默认情况下它们不能被本地配置覆盖
。而 application.yml/.properties
的配置项可以被覆盖。
可通过参数spring.cloud.bootstrap.enabled=true
完全禁用bootstrap
。
1.4 bootstrap(.yml/.properties)应用
- 配置
alibaba-nacos-config
基本连接信息,用于获取远程所需配置。alibaba-nacos-config
基本连接信息就不能写到application.yml/.properties
中等到Application Context
初始化时才读取。必须在bootstrap.yml/.properties
里配置,在初始化Bootstrap Context
时完成读取, 在Application Context
初始化时利用已读取的alibaba-nacos-config
基本连接信息从alibaba-nacos-config
中获取所需的远程配置信息。 - 一些固定的不希望被覆盖的属性,如程序的名字。
- 一些加解密的场景。
二、application多profile配置
更多详细配置及说明请见官网:
https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#boot-features-external-config
3.1 启动时No active profile set, falling back to 1 default profile: “default”
相信有不少细心小伙伴在新启动一个spring boot
项目时候会发现这样一条信息no active profile set, falling back to default profiles: default
。为什么会出现这样的提示呢,我们先来看看profile
,profile
是Spring
对不同环境提供不同配置功能的支持,可以通过激活、 指定参数等方式快速切换环境profile
。举个例子我们在开发,测试,生产用到的配置是不同的,那么通过profile
就可以帮我们指定对应的环境用对应的配置,那么如何来指定呢?
3.2 多profile文件形式
格式:application-{profile}.properties/yml
,在resources
目录下:
默认:application.properties
共用配置:application-common.properties
开发环境:application-dev.properties
生产环境:application-prod.properties
测试环境:application-test.properties
3.3 多profile在application配置激活
在application.properties
中配置:
spring.profiles.active=dev
或在application.yml
中配置:
spring:
profiles:
active: dev
3.3.1 配置示例一
进行多配置激活,如下:
spring.profiles.active=dev,common
HelloWorldApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.concurrent.TimeUnit;
@SpringBootApplication
public class HelloWorldApplication {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(HelloWorldApplication.class, args);
while (true) {
//当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置
String name = applicationContext.getEnvironment().getProperty("name");
String age = applicationContext.getEnvironment().getProperty("age");
System.err.println("=========>>>>>>>>>>name :" + name + ",age :" + age);
TimeUnit.SECONDS.sleep(1);
}
}
}
application.properties
spring.profiles.active=dev,common
name=default
age=0
application-common.properties
name=common
application-dev.properties
name=dev
age=18
运行结果
3.3.2 配置示例二
若项目同一目录同时存在以下四个文件:
bootstrap.properties
bootstrap.yml
application.properties
application.yml
bootstrap
的配置先于application
的配置加载,同时.properties
的加载又先于.yml
的加载,即加载优先级:
bootstrap.properties -> bootstrap.yml -> application.properties -> application.yml
- 当同一个配置属性在
bootstrap.properties
和bootstrap.yml
文件中都存在时,那么properties
中的配置会被加载,而忽略yml
文件中的配置(即优先级高的配置覆盖优先级低的配置),不同配置相互互补。此处application(.properties/yml)
同理。 - 当同一配置属性在
bootstrap.properties
和application.properties
中都存在时,那么虽然优先加载bootstrap.properties
但是会被applicatioin.properties
中的配置覆盖,此时则变成了低优先级覆盖高优先的配置,所以网上很多文章所说的高优先级覆盖低优先级其实是不严谨的。 - 不同的配置会进行互补操作,即
Spring Boot
会读取全部的配置文件,加载所有不同的配置项,汇成一个总的配置。
3.3.3 配置示例三
若项目同一目录同时存在以下四个文件:
bootstrap-dev.yml
bootstrap.properties
application-dev.yml
application.properties
此时的加载优先级变为:
bootstrap-dev.yml -> bootstrap.properties -> application-dev.yml -> application.properties。
且同属性配置的覆盖问题和之前一样:
- 在同为
bootstrap
或同为application
的情况下,优先级高的覆盖优先级低的。 - 在同时存在
bootstrap
和application
时后者仍会覆盖前者中的配置。
举例1:假如此时只有bootstrap-dev.yml
和bootstrap.properties
且存在相同配置,则使用bootstrap-dev.yml
中的配置,此时遵循高优先级覆盖低优先级。
举例2:假如此时有bootstrap-dev.yml
、bootstrap.properties
及application.properties
且存在相同配置,则使用application.properties
中的配置,遵循application
覆盖bootstrap
原则,同样此时变成了低优先级覆盖高优先级。
注意:如
bootstrap
中配置spring.profiles.active: dev
,并在application
中配置spring.profiles.active: test
,此时读取的bootstrap-{profile}.properties/yml
和application-{profile}.properties/yml
中参数{profile}
为dev
即application
中配置未生效。
三、application配置文件加载顺序
通常情况下,Spring Boot
在启动时会将 resources
目录下的 application.properties
或 apllication.yml
作为其默认配置文件,我们可以在该配置文件中对项目进行配置,但这并不意味着 Spring Boot
项目中只能存在一个 application.properties
或 application.yml
,Spring Boot
项目中可以存在多个 application.properties
或 apllication.yml
。
上图中的节点说明如下:
- /myBoot:表示 JAR 包所在目录,目录名称自定义;
- /childDir:表示 JAR 包所在目录下 config 目录的子目录,目录名自定义;
- JAR:表示 Spring Boot 项目打包生成的 JAR;
- 其余带有“/”标识的目录的目录名称均不能修改。
- 红色数字:表示该配置文件的优先级,数字越小优先级越高。
这些配置文件得优先级顺序,遵循以下规则:
- 先加载 JAR 包外的配置文件,再加载 JAR 包内的配置文件;
- 先加载 config 目录内的配置文件,再加载 config 目录外的配置文件;
- 先加载 config 子目录下的配置文件,再加载 config 目录下的配置文件;
- 先加载 appliction-{profile}.properties/yml,再加载 application.properties/yml;
- 先加载 .properties 文件,再加载 .yml 文件
四、Spring Boot常用外部配置加载方式
以下是常用的 Spring Boot 配置形式及其加载顺序(优先级由高到低):
- 命令行参数
所有的配置都可以在命令行上进行指定:
java -jar {Jar文件名} --{参数1}={参数值1} --{参数2}={参数值2}
例如,可以通过指定 --spring.config.location
来改变默认的配置文件位置,通过指定 --spring.profiles.active
激活环境:
java -jar properties-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:./ --spring.profiles.active=test
- Java 系统属性(System.getProperties())
例如,可以通过指定 -Dspring.profiles.active
激活环境:
java -jar properties-0.0.1-SNAPSHOT.jar -Dspring.profiles.active=test
-
操作系统环境变量
-
jar
包外部的application-{profile}.properties
或application-{profile}.yml
(带spring.profile
)配置文件。 -
jar
包内部的application-{profile}.properties
或application-{profile}.yml
(带spring.profile
)配置文件。 -
jar
包外部的application.properties
或application.yml
(不带spring.profile
)配置文件。 -
jar
包内部的application.properties
或application.yml
(不带spring.profile
)配置文件。 -
@Configuration
注解类上的@PropertySource
指定的配置文件 -
通过
SpringApplication.setDefaultProperties
指定的默认属性
以上所有形式的配置都会被加载,当存在相同配置内容时,高优先级的配置会覆盖低优先级的配置;存在不同的配置内容时,高优先级和低优先级的配置内容取并集,共同生效,形成互补配置,大体顺序如下:program arguments
> VM options
> Enviroment variables
> properties
文件 > yml
文件。