Spring Boot 多环境配置:dev / test / prod 与 profile 激活
企业级项目里,同一套代码通常要跑在三个环境:
- dev:开发环境,连本地库,日志尽量详细
- test:测试环境,连测试库和测试中间件
- prod:生产环境,连正式库,配置更严格、更安全
Spring Boot 用 Profile 把这些差异拆开:公共配置放一份,每个环境再各放一份覆盖项。切换环境时不改代码,只激活对应 profile。
配置文件怎么拆
在 src/main/resources/ 下准备四份文件:
src/main/resources/
├── application.properties # 所有环境通用配置
├── application-dev.properties # 开发环境特殊配置
├── application-test.properties # 测试环境特殊配置
└── application-prod.properties # 生产环境特殊配置
YAML 也一样,只是后缀改成 .yml:application.yml、application-dev.yml 等。同一套环境不要 properties 和 yml 混用同一组 key,避免覆盖关系难排查。
加载规则可以记两句:
- 先加载
application.properties/application.yml - 再加载
application-{profile}.properties/application-{profile}.yml,同名配置以后者为准
也就是说:公共默认值写在通用文件里,环境差异写在 application-dev/test/prod 里覆盖。
各文件写什么
下面用最常见的差异举例:数据源、端口、日志、Redis。真实项目请换成你们自己的地址和账号,不要把生产密码提交进仓库。
application.properties:通用配置
# 企业级项目开发中,一般项目默认会激活 dev 环境
spring.profiles.active=dev
# 应用名、公共端口等不随环境大变的项
spring.application.name=demo-service
server.port=8080
# 公共日志格式(级别可在各环境覆盖)
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
通用文件只放「所有环境都一样」或「给一个安全默认值」的内容。数据库密码、生产 Redis、正式密钥不要写在这里。
application-dev.properties:开发环境
server.port=8080
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.redis.host=127.0.0.1
spring.redis.port=6379
logging.level.root=INFO
logging.level.com.example=DEBUG
开发环境优先本地可启动:本地 MySQL、本地 Redis、DEBUG 日志。
application-test.properties:测试环境
server.port=8080
spring.datasource.url=jdbc:mysql://test-db:3306/demo_test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=test_user
spring.datasource.password=${DB_PASSWORD}
spring.redis.host=test-redis
spring.redis.port=6379
logging.level.root=INFO
logging.level.com.example=INFO
测试库地址、账号与开发不同。密码建议用环境变量或配置中心注入,不要明文写死。
application-prod.properties:生产环境
server.port=8080
spring.datasource.url=jdbc:mysql://prod-db:3306/demo_prod?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=prod_user
spring.datasource.password=${DB_PASSWORD}
spring.redis.host=prod-redis
spring.redis.port=6379
logging.level.root=WARN
logging.level.com.example=INFO
生产配置要更保守:日志不要 DEBUG,密钥走环境变量或密钥管理,连接地址指向正式集群。
怎么激活 Profile
Spring Boot 识别 spring.profiles.active。常用三种写法,优先级从高到低可以简单记:命令行参数 > 操作系统环境变量 > 配置文件。实际排查时以启动日志里的 The following 1 profile is active: "xxx" 为准。
1. 写在 application.properties / application.yml(日常开发默认)
# 企业级项目开发中,一般项目默认会激活 dev 环境
spring.profiles.active=dev
YAML 写法:
spring:
profiles:
active: dev
本地 mvn spring-boot:run 或 IDE 直接启动时,不传任何参数就会走 dev。这是团队里最省事的默认方式。
2. 启动命令指定(生产推荐)
配置文件里即使写了 dev,启动时仍可用命令行覆盖:
# 企业级项目开发中,针对生产环境,一般通过启动命令再指定激活 prod 环境
java -jar $APP_NAME --spring.profiles.active=prod
测试环境同理:
java -jar $APP_NAME --spring.profiles.active=test
Maven 开发启动也可以带参数:
mvn spring-boot:run -Dspring-boot.run.arguments=--spring.profiles.active=test
生产发布脚本只改这一处,不必改打包进去的 application.properties,避免「打包是 dev、线上还是 dev」这种事故。
3. 操作系统环境变量(用得相对少)
export SPRING_PROFILES_ACTIVE=prod
java -jar $APP_NAME
Windows PowerShell:
$env:SPRING_PROFILES_ACTIVE = "prod"
java -jar demo-service.jar
容器和 K8s 里比较常见:Deployment 的 env 里设置 SPRING_PROFILES_ACTIVE=prod,镜像不用为每个环境打一份。本地开发较少用这种方式。
IDE 里也可以配:Run Configuration → Environment / VM options / Program arguments,任选一种,不要三处各写一个不同的 profile。
启动后如何确认当前环境
看启动日志:
The following 1 profile is active: "dev"
或在代码里读取:
@RestController
@RequiredArgsConstructor
public class EnvController {
private final Environment environment;
@GetMapping("/env")
public String env() {
return String.join(",", environment.getActiveProfiles());
}
}
生产环境这个接口要鉴权或直接关掉,避免对外暴露环境信息。
和 @Profile 配合
配置文件解决「值不同」,@Profile 解决「某套 Bean 只在某环境存在」:
@Configuration
@Profile("dev")
public class DevOnlyConfig {
@Bean
public CommandLineRunner seedLocalData() {
return args -> {
// 仅开发环境灌测试数据
};
}
}
生产切到 prod 后,这个配置类不会加载。
实践建议
- 仓库默认
spring.profiles.active=dev,保证新同事拉下来就能跑。 - 测试 / 生产不要依赖配置文件里的 active,由启动命令或容器环境变量指定
test/prod。 - 敏感配置不要进 Git:生产密码、AK/SK 用环境变量、Jasypt 或配置中心。
- 同一个 key 只在一处定义最终值,否则你以为改了
application-prod.properties,其实被命令行或环境变量盖掉了。 - YAML 多文档也可以写 profile,但团队如果已经用
application-xxx.properties,就统一一种风格。
小结
| 文件 | 职责 |
|---|---|
application.properties |
公共配置 + 默认 spring.profiles.active=dev |
application-dev.properties |
本地库、详细日志 |
application-test.properties |
测试库、测试中间件 |
application-prod.properties |
生产库、更严格日志与安全配置 |
激活方式对应三种场景:
- 配置文件:本地默认 dev
java -jar $APP_NAME --spring.profiles.active=prod:生产启动覆盖SPRING_PROFILES_ACTIVE:容器 / 系统环境,用得相对少
把「公共默认 + 环境覆盖 + 启动时明确 active」这三件事做对,多环境就不会再靠改文件、重新打包来切换。