Spring Boot 多环境配置详解
为什么需要多环境配置
在实际项目开发中,通常需要部署到不同环境:
- 开发环境 (dev):本地开发调试
- 测试环境 (test):QA 测试验证
- 预发布环境 (staging):上线前最终验证
- 生产环境 (prod):正式对外服务
不同环境需要不同的配置:数据库连接、日志级别、服务端点等。
实现方式一:Profile-specific 配置文件
1. 配置文件命名规则
shellapplication.yml # 默认配置(所有环境共享) application-dev.yml # 开发环境配置 application-test.yml # 测试环境配置 application-staging.yml # 预发布环境配置 application-prod.yml # 生产环境配置
2. 配置文件示例
application.yml(默认配置)
yamlspring: 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)
yamlspring: 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 系统属性
bashjava -Dspring.profiles.active=prod -jar myapp.jar
方式5:IDE 配置
IntelliJ IDEA:
- Run → Edit Configurations → Active profiles:
dev
Profile 分组(Spring Boot 2.4+)
可以将多个 Profile 组合成一个组:
yamlspring: profiles: group: local: - dev - local-db - local-cache production: - prod - prod-db - prod-cache - prod-mq
使用:
bashjava -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 配置文件加载优先级(从高到低):
- 命令行参数
java:comp/envJNDI 属性- Java 系统属性 (
System.getProperties()) - 操作系统环境变量
RandomValuePropertySource- jar 包外部的
application-{profile}.properties - jar 包内部的
application-{profile}.properties - jar 包外部的
application.properties - jar 包内部的
application.properties - @PropertySource 注解
- SpringApplication 默认属性
重要规则:
application-{profile}.yml会覆盖application.yml中的同名配置- 高优先级的配置会覆盖低优先级的同名配置
敏感信息加密
生产环境密码等敏感信息不应明文存储:
方案1:环境变量
yamlspring: 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>
yamlspring: 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?
yamlspring: profiles: default: dev # 当没有指定时默认使用
总结
| 特性 | 说明 |
|---|---|
| 配置文件分离 | application-{profile}.yml |
| 单文件多文档 | 使用 --- 分隔 |
| 激活方式 | 配置、命令行、环境变量、JVM 参数 |
| 条件 Bean | @Profile 注解 |
| Profile 分组 | spring.profiles.group |
| 优先级 | 命令行 > 环境变量 > 配置文件 |