前言
在项目开发时,我们经常需要在不同的运行环境中进行切换,典型的场景包括:开发环境dev
,测试环境test
以及 发布环境prod
。
不同的环境可能会对应不同的配置内容,如果手动更改运行环境配置,会显得非常繁琐与低效。
因此,Spring Boot 提供了一套机制可以很容易地让我们进行多环境配置。
多环境配置
假设现在我们需要往返于两个运行环境:开发环境dev
和 测试环境test
。
Spring Boot 提供了一套多环境配置机制,称为:Profile-specific Properties,可以将其理解为 环境相关配置文件。
Profile-specific Properties 多环境配置的具体步骤如下所示:
-
首先,为不同的运行环境创建不同的配置文件,其命名规范格式为:
application-{profile}.yml
。对应我们的例子,就是需要创建如下两个配置文件:
-
application-dev.yml
:开发环境配置文件,假设其配置内容如下:server: port: 8081
-
application-test.yml
:测试环境配置文件,假设其配置内容如下:server: port: 8082
-
-
然后,在全局配置文件
application.yml
文件中,通过属性spring.profiles.active
来指定应用运行的具体环境:# 使用环境 dev spring: profiles: active: dev
以上,我们就完成了多环境配置,运行程序,结果如下:
可以看到,成功运行在开发环境dev
中,并且相应的配置选项也生效了。
注:如果没有指定具体环境配置文件,那么 Spring Boot 默认加载application-default.properties
配置文件,相当于application.yml
默认配置选项:
spring:
profiles:
active: default
其他
除了上述最为推荐的方式进行多环境配置外,Spring Boot 还提供了许多其他方式进行配置,下面简单介绍几种:
-
代码动态配置:可以通过
SpringApplication.setAdditionalProfiles(..)
方法设置/添加运行环境,如下所示:@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); app.setAdditionalProfiles("dev"); app.run(args); } }
-
Maven 配置运行环境:可以使用 spring-boot-maven-plugin 来指定应用的运行环境,如下所示:
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <profiles> <profile>dev</profile> </profiles> </configuration> </plugin> </plugins>
然后执行命令:
mvn spring-boot:run
,启动应用。
注:当开启了多个运行环境时,最终的配置由最后一个环境决定。
比如,spring.profiles.active
属性加载晚于SpringApplication
相关 API 设置,因此其指定的环境配置文件中的配置生效。
附录
-
指定组件加载于特定环境:在源码中,可以通过
@Profile
等注解指定具体环境配置,当应用运行于该环境时,组件就会被激活加载。比如,当应用运行在开发环境
dev
时,加载组件,如下所示:@Component @Profile("dev") // dev 环境时,加载组件 public class ProfileBean{...}
如果想实现的是在特定环境未激活时,进行组件加载,那么可如下操作:
@Component @Profile("!dev") // 不是 dev 环境时,加载组件 public class ProfileBean{...}
结合
@Profile
和@ConfigurationProperties
还可以实现对环境变量的获取,比如:现在我们在不同的环境配置文件中自定义一个变量,如下:
# application-dev.yml com: yn: mode: development msg: You are in development mode # application-test.yml com: yn: mode: test msg: You are in test mode
然后在代码中,指定使用开发环境
dev
,如下所示:@RestController @RequestMapping("profile") public class ProfilesController { @Autowired private ProfileBean profile; @GetMapping("/") public String index() { return String.format("%s: %s", this.profile.mode, this.profile.msg); } @ConfigurationProperties(prefix = "com.yn") @Profile("dev") // 指定加载环境 @Setter // lombok public static class ProfileBean { private String mode; private String msg; } }
最后,由于上述中
@ConfigurationProperties
注解的类是静态内部类,无法被直接扫描得到,因此可通过@EnableConfigurationProperties
注解手动注册该 Bean,如下代码所示:@SpringBootApplication @EnableConfigurationProperties({ProfilesController.ProfileBean.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
以上,就完成指定加载具体环境配置文件读取功能了。
注:如果
@ConfigurationProperties
注解的 Bean 是通过@EnableConfigurationProperties
进行注册的,那么@Profile
注解所在的@Configuration
类上,需要同时带有注解@EnableConfigurationProperties
。
如果@ConfigurationProperties
是被自动扫描到的,那么@Profile
只需注解在带有@ConfigurationProperties
注解的类上即可。也即在 Spring Boot 中,我们单独创建一个 Bean,只要位于
@SpringBootApplication
注解的包路径内,就可以被自动扫描到,此时@EnableConfigurationProperties
可以忽略不写,如下代码所示:package com.yn.profiles.entity; ... @Component //@EnableConfigurationProperties // 可写可不写 @ConfigurationProperties(prefix = "com.yn") @Profile("dev") @Data public class ProfileBean { private String mode; private String msg; }
只需直接定义一个 Bean,并为其添加相应注解即可,无需其他操作,Spring Boot 会自动扫描到该 Bean 并进行加载。