目录

Spring Boot - 多环境配置

# 简介

在实际的项目开发中,一个项目通常会存在多个环境,例如,开发环境、测试环境和生产环境等。不同环境的配置也不尽相同,例如开发环境使用的是开发数据库,测试环境使用的是测试数据库,而生产环境使用的是线上的正式数据库。

Profile 为在不同环境下使用不同的配置提供了支持,我们可以通过激活、指定参数等方式快速切换环境。

# 多 Profile 文件方式

Spring Boot 的配置文件共有两种形式:.properties 文件和 .yml 文件,不管哪种形式,它们都能通过文件名的命名形式区分出不同的环境的配置,文件命名格式为:

application-{profile}.properties/yml
1

其中,{profile} 一般为各个环境的名称或简称,例如 dev、test 和 prod 等等,这个根据自己的场景来定义。

# 环境配置

resources 下添加 4 个配置文件:

  • application.yml:主配置文件,任意时候都生效
  • application-dev.yml:开发环境配置文件
  • application-test.yml:测试环境配置文件
  • application-prod.yml:生产环境配置文件

定义了这些文件,那么想使用 dev 环境的配置,则在主配置文件切换环境:

spring:
  profiles:
    active: dev # 对应 {profile}
1
2
3

则代表使用 application-dev.yml 的配置信息。

值得注意的是:application.yml 主配置文件不管任何环境都会生效。

application-{profile}.yml 文件和 application.yml 文件的配置项都相同的情况下,profile 优先级高于 application 的配置。

也可以额外添加生效文件,而不是激活替换。比如:

spring:
  profiles:
    active: dev
    include: 
      - test
      - prod
1
2
3
4
5
6

# Profile 分组

当我们想使用多个环境的配置文件时候,可以这样:

spring:
  profiles:
    active: dev,test
1
2
3

当然也可以进行分组:

spring:
  profiles:
    group:
      youngkbt: dev,test
1
2
3
4

然后激活 youngkbt 组

spring:
  profiles:
    active: youngkbt
1
2
3

运行 jar 包的时候也可以覆盖配置文件对环境的配置:java –jar xxx.jar --spring.profiles.active=dev

# @Profile 注解

当配置了环境变量,那么就对应的环境变量配置文件就会生效,这是针对变量而言,此外我们可以指定哪些组件在什么环境才允许被加载到 Spring 容器里。

比如指定某个组件只有在 dev 环境才被加载到容器里,如:

@Profile("dev")
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello Spring Boot";
    }
}

1
2
3
4
5
6
7
8
9
10

此时该容器在 dev 环境才会注入到容器里,也就是处于其他环境,访问 /hello 是失效的。

# 外部化配置

场景:线上应用如何 快速修改配置,并应 用最新配置

  • SpringBoot 使用 配置优先级 + 外部配置 简化配置更新、简化运维。
  • 只需要给 jar 应用所在的文件夹放一个 application.yml 最新配置文件,重启项目就能自动应用最新配置

# 配置优先级

Spring Boot 允许将 配置外部化,以便可以在不同的环境中使用相同的应用程序代码。

我们可以使用各种 外部配置源,包括 Java Properties 文件、YAML 文件、环境变量和命令行参数。

@Value 可以获取值,也可以用 @ConfigurationProperties 将所有属性绑定到 java object 中。

以下是 SpringBoot 属性源加载顺序。后面的会覆盖前面的值。由低到高,高优先级配置覆盖低优先级:

  1. 默认属性(通过 SpringApplication.setDefaultProperties 指定的)
  2. @PropertySource 指定加载的配置(需要写在 @Configuration 类上才可生效)
  3. 配置文件(application.properties/yml 等)
  4. RandomValuePropertySource 支持的 random.* 配置(如:@Value("${random.int}")
  5. OS 环境变量
  6. Java 系统属性(System.getProperties()
  7. JNDI 属性(来自 java:comp/env
  8. ServletContext 初始化参数
  9. ServletConfig 初始化参数
  10. SPRING_APPLICATION_JSON 属性(内置在环境变量或系统属性中的 JSON)
  11. 命令行参数
  12. 测试属性。(@SpringBootTest 进行测试时指定的属性)
  13. 测试类 @TestPropertySource 注解
  14. Devtools 设置的全局属性。($HOME/.config/spring-boot)

结论:配置可以写到很多位置,常见的优先级顺序:命令行 > 配置文件 > springapplication 配置。

Spring Boot 读取 application.yml 配置文件位置也是有优先级的:

配置文件优先级 如下:(后面覆盖前面)

  1. jar 包内application.properties/yml
  2. jar 包内application-{profile}.properties/yml
  3. jar 包外application.properties/yml
  4. jar 包外application-{profile}.properties/yml

建议用一种格式的配置文件。如果 .properties.yml 同时存在,则 .properties 优先。

结论:包外 > 包内。同级情况:profile配置 > application 配置。

所有参数均可由命令行传入,使用 --参数项=参数值,将会被添加到环境变量中,并优先于 配置文件

比如 java -jar app.jar --name="Spring",可以使用 @Value("${name}") 获取。

演示场景:

  • 包内:application.properties 的 server.port=8000
  • 包内:application-dev.properties 的 server.port=9000
  • 包外:application.properties 的 server.port=8001
  • 包外: application-dev.properties 的 server.port=9001

启动端口:命令行 > 9001 > 8001 > 9000 > 8000

# 外部配置

SpringBoot 应用启动时会自动寻找 application.propertiesapplication.yml 位置,进行加载。顺序如下:

当前路径(jar 包根目录下)的配置文件优先级大于项目 resource 下

  • 在项目所在的位置下 config 目录下的 application.yml 大于项目所在的位置的 application.yml
  • 项目 resource 下 config 目录下的 application.yml 大于项目 resource 下的 application.yml

总结:

  • 命令行 > 包外 config 直接子目录 > 包外 config 目录 > 包外根目录 > 包内目录
  • 同级比较:
    • profile 配置 > 默认配置
    • properties 配置 > yaml 配置

规律:最外层的最优先。

  • 命令行 > 所有
  • 包外 > 包内
  • config 目录 > 根目录
  • profile > application

配置不同就都生效(互补),配置相同高优先级覆盖低优先级。

更新时间: 2024/01/17, 05:48:13
最近更新
01
JVM调优
12-10
02
jenkins
12-10
03
Arthas
12-10
更多文章>