相关推荐recommended
Spring Cloud配置application.yml与bootstrap.yml区别及多profile配置 | Spring Cloud 6
作者:mmseoamin日期:2023-12-25

一、前言

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
        

        Spring Cloud配置application.yml与bootstrap.yml区别及多profile配置 | Spring Cloud 6,在这里插入图片描述,第1张

        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
        

        运行结果

        Spring Cloud配置application.yml与bootstrap.yml区别及多profile配置 | Spring Cloud 6,在这里插入图片描述,第2张

        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。

            Spring Cloud配置application.yml与bootstrap.yml区别及多profile配置 | Spring Cloud 6,在这里插入图片描述,第3张

            上图中的节点说明如下:

            • /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文件。