有道无术,术尚可求,有术无道,止于术。
本系列Spring Boot版本2.7.0
Spring Boot应用程序的配置,之前我们介绍过使用application.yml进行应用配置,不仅如此,还支持很多种高级玩法,比如外部配置、占位符、多环境等。
可以通过启动命令行参数的当时添加配置,例如--server.port=9000,在启动时会将其添加到Environment,命令行属性优先级会高于文件配置,但是这种方式如果属性过多,或者被限制就不太好用了。
如果不想将命令行属性添加到Environment 中,可以禁用:
SpringApplication.setAddCommandLineProperties(false)
具体用法可参考:功能篇之SpringApplication启动参数使用详解
Spring Boot支持使用JSON 格式的属性,在应用程序启动时,使用spring.application.json或SPRING_APPLICATION_JSON声明的属性会被解析并添加到Environment中。
例如,使用SPRING_APPLICATION_JSON在UN*X 平台中添加启动属性:
# my.name=test
SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
也可以添加-D参数传递系统属性:
java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
也可以使用--spring.application.json声明:
java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
一般这种方式,比较麻烦,也不太直观,所以基本不会用。。。
应用程序启动时,Spring Boot 将自动在指定目录下查找并加载application.properties、application.yaml文件。
首先我们在下图中的两个位置添加配置文件,然后设置spring: profiles: active: 属性依次从test001-test002

启动项目,发现当前激活的多环境为test002,说明resources/config目录下的配置优先级更高:

如果将配置文件放在类路径的resources目录下,其优先级由高到低如下所示:
resources/config/application.yaml
resources/application.yaml
还支持将配置文件放在Jar 包的同级目录下,它的优先级比上面的更高。

默认支持三种位置,其优先级由高到低如下所示:
config\config\application.yaml
config\application.yaml
application.yaml
除了默认的存放位置,还支持使用 --spring.config.location指定任意位置,此配置会忽略其他位置的文件,比如:
java -jar app.jar --spring.config.location=/home/application-prod.yml
还可以使用spring.config.additional-location增量添加配置,也就是可以读取其他位置的配置,当存在相同属性时会覆盖,最终形成一个有效配置。
默认情况下,当指定的配置数据位置不存在时,Spring Boot 会抛出一个ConfigDataLocationNotFoundException异常,并且启动失败,这时可以添加一个optional:前缀,例如下面执行是,如果/home/application-prod.yml不存在也不会报错:
java -jar app.jar --spring.config.location=optional:/home/application-prod.yml
还可以配置spring.config.on-not-found属性,忽略所有的ConfigDataLocationNotFoundException异常。
在使用外部配置文件时,还支持*通配符,比如有一些 Redis 配置和MySQL配置,需要分开配置,这个时候就可以创建/config/redis/application.properties和config/mysql/application.properties两个文件,Spring Boot 会在包含config/*/中将这两个文件都处理。
在生产环境中我们可以将配置文件放在Jar 包外面,添加当前环境的一些配置,升级的时候只需要替换JAR 包就可以了,这样可以外部化持久配置。
Spring Boot 还支持通过spring.config.import导入配置。
比如导入classpath下两个配置文件,同时导入多个时将按照定义的顺序进行处理,后导入的优先。
spring:
config:
import:
# 导入classpath下default目录下的default.properties配置文件
- classpath:/default/default.properties
# 导入classpath下service目录下的service.yml配置文件
- classpath:/service/service.yml
然后可以通过 @Value或者环境获取当前配置:

还支持从 Consul、Apache ZooKeeper 或 Netflix Archaius中直接导入配置,还支持Kubernetes 中的 ConfigMaps和Secrets 导入,具体的用法可以需要用时再去了解。
还支持导入无扩展名文件,比如有一个配置文件一个/etc/config/myconfig,没有后缀名,我们可以通过一下方式,将其导入为YML 格式:
spring.config.import=file:/etc/config/myconfig[.yaml]
默认采用application作为配置文件名,可以自定义配置文件名,比如我将其改为custom.yml,然后添加一个运行参数--spring.config.name=custom:

或者在 java -jar启动的时候,也可以指定自定义配置文件名:
java -jar app.jar --spring.config.name=custom
配置文件支持使用${name}占位符从Environment获取属性值,还可以使用${name:default}指定一个默认值。
比如,可以配置从Environment中获取数据库的用户名和密码,如果没有时,将会采用默认配置。
spring:
datasource:
username: ${db_name:root}
password: ${db_pwd:123456}
Spring Boot 将单个配置文件拆分为多个逻辑文档,文档从上到下按顺序处理,后面的可以覆盖前面文档中定义的属性。
对于application.yml文件,使用标准的 YAML 多文档语法,三个连续的连字符代表一个文档的结束,以及下一个文档的开始。
如下所示,配置了多个相同属性的逻辑文档配置,后面相同属性的配置会替换前面的配置:
server:
port: 9004
---
server:
port: 9005
注意:不能使用@PropertySource、@TestPropertySource注解加载多文档属性文件。
Spring Boot 在配置文件中,直接生成随机数,例如随机整数、长整数、uuid 或字符串,如下例所示:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
在实际开发中,存在开发、测试、预发布、生产等各种环境,每个环境的数据库配置肯定是不一样的,如果每次更新发布,都去修改配置,十分麻烦,所以Spring Boot为我们提供了多环境的配置功能。
首先,我们使用application-{profile}.yml格式来创建不同环境的配置文件,然后根据环境配置不同的属性。

现在直接启动应用程序,使用的是不带后缀的application.yml配置。
如果需要切换环境,可以在application.yml添加需要激活的环境,比如配置为dev,则会读取application-dev.yml配置。
spring:
profiles:
active: dev
当我们不同环境启动时,使用--spring.profiles.active=环境名就可以实现多环境切换了,比如启动时读取生产环境的配置:
java -jar app.jar --spring.profiles.active=prod
但是如果是一个产品,需要部署很多套,这个时候就比较麻烦了,所以现在一般采用配置中心来实现。