乐闻世界logo
搜索文章和话题

Spring Boot 中如何实现多环境配置?

3月6日 21:58

Spring Boot 多环境配置详解

为什么需要多环境配置

在实际项目开发中,通常需要部署到不同环境:

  • 开发环境 (dev):本地开发调试
  • 测试环境 (test):QA 测试验证
  • 预发布环境 (staging):上线前最终验证
  • 生产环境 (prod):正式对外服务

不同环境需要不同的配置:数据库连接、日志级别、服务端点等。

实现方式一:Profile-specific 配置文件

1. 配置文件命名规则

shell
application.yml # 默认配置(所有环境共享) application-dev.yml # 开发环境配置 application-test.yml # 测试环境配置 application-staging.yml # 预发布环境配置 application-prod.yml # 生产环境配置

2. 配置文件示例

application.yml(默认配置)

yaml
spring: application: name: my-service profiles: active: dev # 默认激活 dev 环境 server: port: 8080 # 公共配置 logging: level: root: INFO

application-dev.yml(开发环境)

yaml
# 开发环境特定配置 server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/dev_db username: dev_user password: dev_pass driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true logging: level: com.example: DEBUG org.springframework.jdbc: DEBUG

application-prod.yml(生产环境)

yaml
# 生产环境特定配置 server: port: 80 spring: datasource: url: jdbc:mysql://prod-db.example.com:3306/prod_db username: ${DB_USERNAME} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 50 minimum-idle: 10 jpa: hibernate: ddl-auto: validate show-sql: false logging: level: root: WARN com.example: INFO file: name: /var/log/my-service/app.log

实现方式二:单文件多文档块

Spring Boot 2.4+ 支持在一个 YAML 文件中定义多个 Profile:

yaml
# application.yml spring: application: name: my-service --- spring: config: activate: on-profile: dev server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/dev_db username: dev_user password: dev_pass --- spring: config: activate: on-profile: prod server: port: 80 spring: datasource: url: jdbc:mysql://prod-db.example.com:3306/prod_db username: ${DB_USERNAME} password: ${DB_PASSWORD}

激活 Profile 的方式

方式1:配置文件指定(application.yml)

yaml
spring: profiles: active: dev

方式2:命令行参数

bash
# 启动时指定环境 java -jar myapp.jar --spring.profiles.active=prod # 或者 java -jar myapp.jar -Dspring.profiles.active=prod

方式3:环境变量

bash
# Linux/Mac export SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar # Windows set SPRING_PROFILES_ACTIVE=prod java -jar myapp.jar

方式4:JVM 系统属性

bash
java -Dspring.profiles.active=prod -jar myapp.jar

方式5:IDE 配置

IntelliJ IDEA:

  • Run → Edit Configurations → Active profiles: dev

Profile 分组(Spring Boot 2.4+)

可以将多个 Profile 组合成一个组:

yaml
spring: profiles: group: local: - dev - local-db - local-cache production: - prod - prod-db - prod-cache - prod-mq

使用:

bash
java -jar myapp.jar --spring.profiles.active=local # 实际激活: dev, local-db, local-cache

条件化 Bean 配置

使用 @Profile 注解根据环境创建不同的 Bean:

java
@Configuration public class DataSourceConfig { @Bean @Profile("dev") public DataSource devDataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/dev_db"); config.setUsername("dev_user"); config.setPassword("dev_pass"); return new HikariDataSource(config); } @Bean @Profile("prod") public DataSource prodDataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://prod-db.example.com:3306/prod_db"); config.setUsername(System.getenv("DB_USERNAME")); config.setPassword(System.getenv("DB_PASSWORD")); config.setMaximumPoolSize(50); return new HikariDataSource(config); } @Bean @Profile("!prod") // 非生产环境 public MockService mockService() { return new MockService(); } }

在代码中获取当前 Profile

java
@Component public class EnvironmentChecker implements CommandLineRunner { @Autowired private Environment environment; @Override public void run(String... args) { // 获取所有激活的 profiles String[] activeProfiles = environment.getActiveProfiles(); System.out.println("Active profiles: " + String.join(", ", activeProfiles)); // 判断是否包含某个 profile if (environment.acceptsProfiles(Profiles.of("dev"))) { System.out.println("Development mode"); } // 判断是否生产环境 boolean isProd = Arrays.asList(activeProfiles).contains("prod"); } }

配置文件加载顺序与优先级

Spring Boot 配置文件加载优先级(从高到低):

  1. 命令行参数
  2. java:comp/env JNDI 属性
  3. Java 系统属性 (System.getProperties())
  4. 操作系统环境变量
  5. RandomValuePropertySource
  6. jar 包外部的 application-{profile}.properties
  7. jar 包内部的 application-{profile}.properties
  8. jar 包外部的 application.properties
  9. jar 包内部的 application.properties
  10. @PropertySource 注解
  11. SpringApplication 默认属性

重要规则

  • application-{profile}.yml 会覆盖 application.yml 中的同名配置
  • 高优先级的配置会覆盖低优先级的同名配置

敏感信息加密

生产环境密码等敏感信息不应明文存储:

方案1:环境变量

yaml
spring: datasource: password: ${DB_PASSWORD}

方案2:Jasypt 加密

xml
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.5</version> </dependency>
yaml
spring: datasource: password: ENC(加密后的密文) jasypt: encryptor: password: ${JASYPT_ENCRYPTOR_PASSWORD}

最佳实践

1. 配置分层结构

yaml
# application.yml - 只放真正公共的配置 spring: application: name: my-service jackson: date-format: yyyy-MM-dd HH:mm:ss --- # 各环境特定配置放在单独文件

2. 使用配置属性类

java
@ConfigurationProperties(prefix = "app") @Component public class AppProperties { private String name; private String version; private Map<String, String> metadata; // getters and setters }

3. 生产环境配置检查清单

  • 关闭调试模式:debug: false
  • 关闭 SQL 打印:show-sql: false
  • 设置合适的日志级别
  • 配置连接池参数
  • 使用环境变量存储敏感信息
  • 配置健康检查端点
  • 设置合理的超时参数

4. 本地开发便利配置

yaml
# application-local.yml spring: devtools: restart: enabled: true livereload: enabled: true h2: console: enabled: true path: /h2-console

常见问题

Q1: Profile 不生效?

  • 检查配置文件命名是否正确:application-{profile}.yml
  • 确认 Profile 已正确激活
  • 检查是否有拼写错误

Q2: 多个 Profile 如何同时激活?

bash
--spring.profiles.active=dev,local-db

Q3: 如何设置默认 Profile?

yaml
spring: profiles: default: dev # 当没有指定时默认使用

总结

特性说明
配置文件分离application-{profile}.yml
单文件多文档使用 --- 分隔
激活方式配置、命令行、环境变量、JVM 参数
条件 Bean@Profile 注解
Profile 分组spring.profiles.group
优先级命令行 > 环境变量 > 配置文件
标签:Spring Boot