10、Spring Boot 3.x 特性-Profiles&多环境配置

Spring Profiles 提供一种方法来隔离应用程序配置的各个部分,并使其仅在某些环境中可用。

并且和application属性文件一样,Spring Boot也会尝试使用命名约定application-{profile}来加载特定配置文件的文件。

例如,如果你的应用程序激活一个名为prod的配置文件并使用YAML文件,那么application.ymlapplication-prod.yml文件将会被加载。

一、Profiles激活

1.注解激活

任何@Component@Configuration@ConfigurationProperties都可以用@Profile标记来限制加载。

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {
   
     

    // ...

}

如果@ConfigurationProperties bean是通过@ Enableconconfigurationproperties而不是自动扫描注册的,则需要在具有@Enableconconfigurationproperties注解的@Configuration类上指定@Profile注释。在扫描@ConfigurationProperties的情况下,@Profile可以在@ConfigurationProperties类本身上指定。

2.配置属性激活

除了注解激活配置属性,你可以在application.properties中使用spring.profiles.active配置环境属性激活profiles,

spring:
  profiles:
    active: "dev,hsqldb"

你也可以在命令行中指定它,使用下面的开关:--spring.profiles.active=dev,hsqldb

spring.profiles.activespring.profiles.default只能在non-profile 文档中使用。这意味着它们不能包含在spring.config.activate.on-profile激活的配置文件或profile文件中使用。
例如:可以在application.properties中使用spring.profiles.active属性,但是在application-dev.properties中不可以使用,启动时程序会报如下错误:

Property 'spring.profiles.active' imported from location 'class path resource [application-dev.properties]' is invalid in a profile specific resource [origin: class path resource [application-dev.properties] 

考虑如下on-profile文件:

# 这个文档有效
spring:
  profiles:
    active: "prod"
---
# 无效
spring:
  config:
    activate:
      on-profile: "prod"
  profiles:
    active: "metrics"

3.添加多个激活的Profiles

spring.profiles.active属性规则与其他属性相同的排序规则:最高优先级的PropertySource生效。
这意味着可以在application.properties中激活profile,然后使用命令行开关替换它。
有时,让属性添加到激活profile而不是替换它们是很有用的。

spring.profiles.include属性可用于在spring.profiles.active属性激活的配置文件之上添加激活的配置文件。SpringApplication入口点也有一个Java API,用于设置额外的配置文件。参见SpringApplication中的setAdditionalProfiles()方法。

例如,当运行具有以下属性的应用程序时,commonlocal profiles文件都会被激活,
当它使用——spring.profiles.active开关:

spring:
  profiles:
    include:
      - "common"
      - "local"

spring.profiles.active一样spring.profiles.include只能在non-profile 文档中使用。这意味着它们不能包含在spring.config.activate.on-profile激活的配置文件或profile文件中使用。

4.Profiles组

有时候,在应用程序中定义和使用的profiles粒度太细,使用起来很麻烦。例如,您可能使用proddbprodmq profiles 文件来独立启用数据库和消息传递特性。
为了帮助实现这一点,Spring Boot允许定义profile组。配置文件组允许为相关的配置文件组定义一个逻辑名称。
例如,我们可以创建一个由proddbprodmq profile组成的production组。

spring:
  profiles:
    group:
      production:
      - "proddb"
      - "prodmq"

我们的应用程序现在可以使用——spring.profiles.active =production一次激活productionproddbprodmq配置文件。

二、多环境配置

通常正常开发过程中会存在多套环境,常见的开发环境(dev)、测试环境(test)、生产环境(prod),这种情况下我们可以新建多个application.properties(或yml)
 

spring.profiles.active 属性可以指定当前设置的环境,以此来选择适合的配置文件,例如当spring.profiles.active=prd时,系统将加载application.propertiesapplication-prod.properties配置文件。

在IDEA中可以在运行配置时指定:
 

 
 
上述方法多环境配置文件力度比较粗,假如每个环境存在多个配置文件 redis,mysql,mq单独拆开。针对这种情况可以使用Profile Group:
 
然后每个配置文件添加一个变量用于测试:
 
 
测试代码:

@SpringBootApplication
public class SpringProfilesConfigApplication {
   
     

    @Value("${spring.profiles.active}")
    private String env;

    @Value("${pf.mq}")
    private String mq;
    @Value("${pf.redis}")
    private String redis;
    @Value("${pf.mysql}")
    private String mysql;

    public static void main(String[] args) {
   
     
        SpringApplication.run(SpringProfilesConfigApplication.class, args);
    }

    @Component
    public class MyApplicationRunner implements ApplicationRunner {
   
     
        @Override
        public void run(ApplicationArguments args) throws Exception {
   
     
            System.out.printf("当前激活的配置环境是{%s}:mq:%s,mysql:%s,redis:%s", env, mq, mysql, redis);
        }
    }
}

当激活prd环境时:

 

三、maven多环境打包

spring.profiles.active 属性的设置简单的方式application.properties指定,但是存在一个问题,单程序打包时不能每次去更改配置这样非常麻烦,那么可以把这个属性值设置成变量,maven编译打包时动态传入。比如在application.properties文件中配置如下:

spring.profiles.active=@profile.active@

1、 在pom.xml中添加如下内容,多个环境添加多个profile节点即可,但是需要指定一个默认的环境:;

<profiles>  
    <profile>  
        <id>dev</id>  
        <properties>  
            <!-- 环境标识,与配置文件的名称相对应,标签变量要与profile.active保持一致 ->  
            <profile.active>dev</profile.active>  
        </properties>  
        <activation>  
            <!-- 默认环境 -->  
            <activeByDefault>true</activeByDefault>  
        </activation>  
    </profile>  
    <profile>  
        <id>test</id>  
        <properties>  
            <profile.active>test</profile.active>  
        </properties>  
    </profile>  
    <profile>  
        <id>prod</id>  
        <properties>  
            <profile.active>prod</profile.active>  
        </properties>  
    </profile>  
</profiles>  

接下来添加maven打包插件

 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                <mainClass>com.example.springprofilesconfig.SpringProfilesConfigApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!--创建一个自动可执行的jar或war文件 -->
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

添加上面插件后IDEA可以选择对应profile环境
 
执行compile,查看编译打包后的配置文件如下:
 

@profile.active@变量已被替换成对应的proflie环境值。

总结

本文主要是基于Profiles特性来支持多环境配置属性的实现,以及maven多环境打包,其实大多数生产环境配置类文件,一般都使用分布式配置相关的中间件,比如Nacos,Apollo等等。