cd ..

SpringBoot 外部配置文件的使用和优先级

SpringBoot 提供了灵活的外部配置机制,让我们无需重新打包就能调整应用行为。本文梳理了几种常用的外部配置方式及其优先级关系,帮你在不同部署场景下做出正确选择。

改个端口号,还要重新打包?

你一定遇到过这种场景:项目打成 jar 包部署到服务器上,结果发现端口号冲突了,或者数据库地址要换。难道就为了改一行配置,要重新走一遍构建流程?当然不用。

SpringBoot 早就考虑到了这个问题,它提供了多种外部配置方式,让同一个 jar 包可以在不同环境中灵活运行。掌握这些配置方法和它们的优先级关系,是每个 SpringBoot 开发者的必备技能。

方式一:命令行参数

最简单粗暴的方式,直接在启动命令里加参数:

nohup java -jar myapp.jar --server.port=8081

这种方式适合临时调整,比如排查问题时临时换个端口,或者在不同终端启动多个实例。缺点也很明显——参数一多,命令行就变得又臭又长。

方式二:环境变量

在容器化部署(Docker、K8s)的场景下,环境变量是最主流的配置方式:

export SERVER_PORT=8081
java -jar myapp.jar

SpringBoot 会自动把环境变量映射到对应的配置属性上。规则也很简单:把属性名中的点换成下划线,字母全大写。比如 server.port 对应 SERVER_PORTspring.datasource.url 对应 SPRING_DATASOURCE_URL

这种方式的好处是配置和代码完全解耦,特别适合 12-Factor App 的理念。

方式三:外部配置文件

当需要修改的配置项比较多时,外部配置文件是最合适的选择。

放在 jar 包同级目录

最省事的做法:在 jar 包所在目录创建 application.ymlapplication-{profile}.yml,SpringBoot 启动时会自动加载它,并且优先级高于 jar 包内部的同名文件。

指定配置文件路径

如果配置文件放在别的目录,用 --spring.config.location 来指定:

java -jar myapp.jar --spring.config.location=file:/path/to/application.yml

追加额外配置

有时候你不想替换默认配置,只想在默认基础上加一些覆盖项。这时候用 --spring.config.additional-location

java -jar myapp.jar --spring.config.additional-location=file:/path/to/application-prod.yml --spring.profiles.active=prod

这两个参数的区别很关键:location 会完全替换默认的配置搜索路径,而 additional-location 是在默认路径之外追加。搞混了会导致很多默认配置失效,排查起来很头疼。

配置加载优先级

说了这么多配置方式,那它们之间冲突了怎么办?SpringBoot 有一套明确的优先级规则(从高到低):

  1. 命令行参数
  2. Java 系统属性
  3. 操作系统环境变量
  4. application-{profile}.properties 外部文件
  5. application.properties 外部文件
  6. application-{profile}.properties 内部文件
  7. application.properties 内部文件

核心原则就一句话:越「外部」的配置,优先级越高。命令行参数最高,jar 包内部的配置文件最低。同名属性会被高优先级的覆盖,不同名的则会合并。

还有两点容易踩坑:

  • --spring.config.location 会完全替换默认的配置位置,用的时候要小心
  • --spring.config.additional-location 是追加,不会影响默认配置的加载
  • 后加载的配置会覆盖先加载的同名配置

小结

回到开头的问题——改配置不需要重新打包,只需要选择合适的外部配置方式。日常开发中,我的习惯是:开发环境用 jar 包内部的默认配置,测试和生产环境通过外部配置文件覆盖,临时调试用命令行参数。理解了优先级规则,配置管理就不会乱。