官方文档 https://docs.spring.io/spring-boot/docs/2.7.16/reference/htmlsingle/#features.external-config
Spring Boot允许外部化配置,这样就可以在不同的环境中使用相同的应用程序代码。您可以使用各种外部配置源,包括Java属性文件、YAML文件、环境变量和命令行参数
。
属性值可以使用@Value
注解直接注入到bean中,通过Spring的环境抽象访问,也可以通过@ConfigurationProperties
绑定到结构化对象。
Spring Boot使用了一个非常特殊的PropertySource
顺序,旨在允许合理的值覆盖。后面的属性源可以覆盖前面定义的值。来源按以下顺序考虑(优先级从小到大):
Default properties
(specified by setting SpringApplication.setDefaultProperties).@Configuration
classes.
logging.*
和spring.main.*
在刷新开始之前就要set的配置来说:太晚了Config data
(such as application.properties files).RandomValuePropertySource
that has properties only in random.*.VM options
,使用java -Dage=18
…java:comp/env
.ServletContext init parameters
.ServletConfig init parameters.
@DynamicPropertySource
annotations in your tests.@TestPropertySource
annotations on your tests.$HOME/.config/spring-boot
directory when devtools is active.
最终转换的执行命令: java -Dage=22 -classpath **.jar cn.jhs.spring.boot.App --name=joe
执行结果:name=joe,age=22,sex=M
https://docs.spring.io/spring-boot/docs/2.7.16/reference/htmlsingle/#features.external-config.files
springboot默认会加载application.yaml或application.properties
中的配置信息.
!!!注意: 同名文件,".properties"优先级大于".yaml"
application.properties and YAML
案例说明:
如果你不喜欢用application作为配置文件名,可以通过指定spring.config.name
环境属性来切换到另一个文件名。
# myproject.properties/yaml
java -jar myproject.jar --spring.config.name=myproject
还可以使用spring.config.location
环境属性来引用显式位置。此属性接受一个逗号分隔的列表,其中包含要检查的一个或多个位置。
# 若default.properties与override.properties存在同名的配置,后面的会覆盖前面的; **last-wins**策略
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
#1. 设置 spring.config.additional-location
spring.config.additional-location=optional:classpath:/custom-config/,optional:file:./custom-config/
#2.优先级(优先级从小到大,后面覆盖前面)
## additional-location高于spring.config.location优先级
optional:classpath:/;optional:classpath:/config/
optional:file:./;optional:file:./config/;optional:file:./config/*/
optional:classpath:custom-config/
optional:file:./custom-config/
application-{profile}.properties and YAML
https://docs.spring.io/spring-boot/docs/2.7.16/reference/htmlsingle/#features.external-config.files.profile-specific
Spring Boot还会尝试使用命名约定application-{profile}
来加载特定于profile
的文件。例如,如果您的应用程序激活一个名为prod
的配置文件,那么application.yaml 和 application-prod.yaml
都会被使用。
特定于profile的文件总是覆盖
非特定的配置。
如果指定了多个profile,则采用last-wins策略。例如,如果spring.profiles.active
设置为prod,live
由属性指定,值在application-prod.properties属性可以被application-live.properties中的属性覆盖。
#1. profiles : prod,live
#2. 存在配置文件
/cfg
application-live.properties
/ext
application-live.properties
application-prod.properties
# 3.1 若 spring.config.location=classpath:/cfg/,classpath:/ext/ ,优先级(后面的覆盖前面)
# /cfg 总是会被 /ext 覆盖
/cfg/application-live.properties
/ext/application-prod.properties
/ext/application-live.properties
# 3.2 若 spring.config.location=classpath:/cfg/;classpath:/ext/ (注意是; 不是,)
# # /cfg 和/ext 优先级一致
/ext/application-prod.properties
/cfg/application-live.properties
/ext/application-live.properties
application.properties and YAML
application-{profile}.properties and YAML
yaml可以使用---
分割不同的配置块,当spring.profiles.active=dev
时,配置文件优先级:
此时的environment.getPropertySources().propertySourceList
@Component
@ConfigurationProperties(prefix = "my.cache")
//注意:默认仅支持 *.properties
@PropertySource(value = {"classpath:cache.properties","file:./config/cache.properties"}, ignoreResourceNotFound = true)
public class CacheConfigProperties {
private String name;
private long timeout;
}
这里@PropertySource
引入的资源,跟code顺序无关, 同样按照 file > classpath
的优先级来加载。
所以我们可以在project中填写默认的配置。
部署服务器时,在file目录下,填写实际的配置。
https://docs.spring.io/spring-boot/docs/2.7.16/reference/htmlsingle/#features.external-config.typesafe-configuration-properties.relaxed-binding
Spring Boot使用了一些宽松的规则将环境属性绑定到@ConfigurationProperties bean
上,因此环境属性名和bean属性名不需要完全匹配。
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}