在做 Spring Boot 开发时,你是否遇到过:明明在 application.yml 里改了端口号,结果启动后还是原来的?或者在生产环境下,运维随手改了一个环境变量,程序运行逻辑就变了?
其实,这是因为存在 Spring Boot 配置加载的优先级机制。下面我们用通俗易懂的方式,理清 yml、properties、环境变量、命令行参数到底谁说了算!
🔝 配置优先级全家桶
Spring Boot 的配置来源非常多,但日常开发最常用的其实就那么几种。
为了方便记忆,直接看优先级排行榜:
| 优先级 |
配置来源 |
| 1 (最高) |
命令行参数 (--key=value) |
| 2 |
Java 系统属性 (-Dkey=value) |
| 3 |
操作系统环境变量 |
| 4 |
Jar 包外部配置文件 |
| 5 (最低) |
Jar 包内部配置文件 |
⚔️ 场景:谁能笑到最后?
假设我们的应用叫 my-app,我们要修改 server.port 这个属性。
1. 内部文件:基础版
在代码里的 src/main/resources/application.yml 写了:
server:
port: 8080
💡 结果: 默认端口 8080。
2. 外部文件:运维版
项目打包成 my-app.jar 后,你在 jar 包同级目录下放了一个 application.properties:
server.port=9090
💡 结果: 端口变成了 9090。外部配置会覆盖内部配置,这为运维修改配置提供了便利。
3. 环境变量:容器版
如果你在 Linux 服务器上执行了:
export SERVER_PORT=7070
java -jar my-app.jar
💡 结果: 端口变成了 7070。这在 Docker 或 Kubernetes 等容器化部署中是非常常见的做法。
4. 命令行参数:终极版
你在启动命令里直接加上参数:
java -jar my-app.jar --server.port=6060
💡 结果: 端口最终锁定在 6060!命令行参数拥有最高优先级,它的设定会覆盖所有其他来源的配置。
❓ 疑惑:yml 和 properties 谁更牛?
如果我同一个目录下既有 application.yml 又有 application.properties,谁会生效?
💡 答案:
在 Spring Boot 中,properties 文件的优先级高于 yml 文件。
虽然 yml 格式层级更清晰,但如果两者内容冲突,Spring Boot 会优先采用 properties 文件中的值。因此建议在项目中统一使用一种配置文件格式,避免混淆。
📊 结论总结表
| 优先级 |
配置来源 |
常用场景 |
灵活性 |
| 1 (最高) |
命令行参数 (--key=value) |
临时修改端口、切换激活的 Profile |
⭐⭐⭐⭐⭐ |
| 2 |
Java 系统属性 (-Dkey=value) |
在启动脚本中定义特定参数 |
⭐⭐⭐⭐ |
| 3 |
操作系统环境变量 |
Docker / K8s 容器化部署 |
⭐⭐⭐⭐ |
| 4 |
外部配置文件 (Jar 包外) |
生产环境差异化配置,无需重新打包 |
⭐⭐⭐ |
| 5 (最低) |
内部配置文件 (Jar 包内) |
默认配置、开发环境配置 |
⭐ |
🌟 避坑小贴士
- 层级覆盖而非替换:高优先级的配置只会覆盖与之冲突的 key,其他未冲突的配置项依然会保留并生效。
- 变量名转换:在设置环境变量时,
server.port 这类属性名建议转换成大写加下划线的形式,如 SERVER_PORT,Spring Boot 的松散绑定机制会自动识别。
- 检查 Profile:别忘了
application-dev.yml 这种带特定 Profile 的配置文件,当对应的 Profile 被激活时,它的优先级比通用的 application.yml 更高。
理解 Spring Boot 的配置加载顺序是进行高效开发和运维部署的基础。如果你想深入探讨更多 Spring Boot 或其他 Java 开发中的实用技巧,欢迎在 云栈社区 交流分享。
|