SpringBoot核心特性——多环境配置的那些事

194 阅读3分钟

前言

这次主要讲解一下SpringBoot多环境配置相关的知识点

多环境配置

平常开发、测试、生成环境使用的配置一般都是各自分开的,这里演示一下如何让SpringBoot激活不同环境的配置文件。

创建MyConfig,代码如下:

package geek.springboot.application.configuration;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.beans.factory.annotation.Value;  
import org.springframework.stereotype.Component;  
  
/**  
* 自定义配置  
*  
* @author Bruse  
*/  
@Slf4j  
@Component  
public class MyConfig {  
  
    /**  
    * 姓名  
    * 添加上@Value注解,表示该值从配置中读取  
    */  
    @Value("${name}")  
    private String name;  
  
    /**  
    * 打印name的值  
    */  
    public void printName() {  
        log.info("My name is {}", this.name);  
    }  
  
}

在resources文件夹下分别创建以下application-xxx.yml

application-dev.yml (开发环境)

name: dev

application-prod.yml (生产环境)

name: prod

application-stage(测试环境)

name: stage

application.yml(SpringBoot默认读取)

spring:  
   application:  
     name: MyApp  
  
name: myConfig

启动SpringApplicaiton,调用MyConfig实例的printName(),输出为 My name is myConfig

指定激活单个配置文件

接下来让SpringBoot读取dev(开发环境)配置,只需要在application.yml添加上如下配置:

spring:  
    profiles:  
        active: dev # 这里表示除了加载application.yml外,再加载application-dev.yml,如果要加载application-prod.yml,那就是prod,springboot会对多个application.yml进行整合

重启SpringApplicatio,调用printName(),输出为 My name is dev

可以看到成功读取开发环境的yaml配置,其余环境配置文件切换,只需要把dev换成prod、stage即可

指定激活多个配置文件

MyConfig新增job字段

@Value("${job}")
private String job;

public void printName() {  
    log.info("My name is {} and job is {}", this.name, this.job);  
}

application-prod.yml 删除name配置,且新增job配置

job: java

如果想要同时加载application-dev.yml和application-prod.yml,则需要在application.yml稍作改动

spring:   
   profiles:  
     active: dev,prod

控制台MyConfig输出My name is dev and job is java 说明dev.yml和prod.yml同时被SpringBoot加载

prod.yml删掉name是为了做出明显区分,因为如果dev.yml和prod.yml都存在name的话,那么prod.yml的name:prod会覆盖掉dev.yml的name:dev。

通过Java API指定激活的配置文件

删除application.yml 如下代码

spring:   
   profiles:  
     active: dev,prod

在SpringApplication启动时,通过setAdditionalProfiles()指定要激活的配置文件,关键代码如下:

public static void main(String[] args) {  
    // 初始化SpringApplication  
    SpringApplication springApplication = new SpringApplication(Application.class);  
    // 加载dev、prod配置文件  
    springApplication.setAdditionalProfiles("dev", "prod");  
    // 启动SpringApplication  
    springApplication.run(args);  
}

控制台MyConfig输出My name is dev and job is java

通过命令参数指定激活的文件

除了前面提到的使用application.yml或Java API指定要激活的配置文件外,也可以在Java应用启动时通过命令行参数指定当前激活的配置:

--spring.profiles.active=prod

配置分组

有时候我们的配置文件更加细粒度点,比如生产环境配置不是一股脑全放在application-prod.yml中,而是把数据库、缓存、队列等配置文件都拆分开来,避免prod.yml过于复杂,那这里可以用到SpringBoot 配置分组功能。

注意!!!使用配置分组请注意当前SpringBoot的版本,我原先尝试时无论如何配置分组都是失败的,后来发现是当时用的SpringBoot版本2.3.1.RELEASE过低...后来升级到2.7.14版本才成功。

<parent>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-parent</artifactId>  
    <version>2.7.14</version>  
    <relativePath />  
</parent>

新建一个MiddlewareConfig,代码如下:

package geek.springboot.application.configuration;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.beans.factory.annotation.Value;  
import org.springframework.stereotype.Component;  
  
/**  
* 中间件Config  
*  
* @author Bruse  
*/  
@Slf4j  
@Component  
public class MiddlewareConfig {  
  
    @Value("${dbUrl}")  
    private String dbUrl;  

    @Value("${redisUrl}")  
    private String redisUrl;  
  
    @Override  
    public String toString() {  
        return "MiddlewareConfig{" +  
        "dbUrl='" + dbUrl + '\'' +  
        ", redisUrl='" + redisUrl + '\'' +  
        '}';  
    }  
}

新建application-prod-db.yml (数据库生产环境配置):

dbUrl: 127.0.0.1:3306

新建application-prod-cache.yml(缓存生产环境配置):

redisUrl: 127.0.0.1:6379

application.yml稍作调整:

spring:  
  profiles:  
    group:  
    # 建立一个production分组  
       production: # 以下表示分组文件列表  
         - "prod-db"  
         - "prod-cache"  
         - "prod"  
    active: production # 表示激活production分组,那么分组下的application-prod-db.yml、application-prod-cache.yml、application-prod.yml都会被加载

启动SpringApplicaiton,控制台MiddlewareConfig输出 MiddlewareConfig{dbUrl='127.0.0.1:3306', redisUrl='127.0.0.1:6379'}

@Profile注解

当某些Java Bean需要在特定环境下才被加载时,可以用@Profile注解修饰,作为一个Bean加载的约束。

新建一个ProdConfig,代码如下:

package geek.springboot.application.configuration;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.context.annotation.Profile;  
import org.springframework.stereotype.Component;  
  
import javax.annotation.PostConstruct;  
  
/**  
* 生产环境Config  
*  
* @author Bruse  
*/  
@Slf4j  
@Component  
// 加上Profile,表示当application-prod.yml被加载时,Spring IOC才加载化该Bean  
@Profile("prod")  
public class ProdConfig {  
  
    @PostConstruct  
    public void init() {  
        // Bean初始化时调用  
        log.info("ProdConfig init");  
    }  

}

重启SpringApplication,控制台没有输出ProdConfig init

修改application.yml

spring:   
   profiles:  
      active: prod

重启SpringApplication,这次因为加载了application-prod.yml,控制台输出 ProdConfig init

image.png

@Profile注解除了可以用在@Component修饰的Java Bean外,同样也可以用来限制@Configuration 、@ConfigurationProperties 修饰的Bean加载与否。

结尾

本文章源自《Learn SpringBoot》专栏,感兴趣的话还请关注点赞收藏.

上一篇文章:《SpringBoot核心特性——万字拆解外部配置

下一篇文章:《SpringBoot核心特性——异步任务和定时任务那些事