SpringBoot(30) - Properties(2) - 使用YAML配置
YAML是JSON的超集,因此對於指定分層配置資料來說是一種非常方便的格式。 只要在類路徑上有SnakeYAML庫,SpringApplication類就會自動支援YAML配置。
注:如果使用spring-boot-starter,將通過自動提供SnakeYAML。
1. 載入YAML
Spring Framework提供了兩個方便的類,可用於載入YAML文件。 YamlPropertiesFactoryBean將YAML作為Properties載入,YamlMapFactoryBean將YAML作為Map載入。
例如,下面的配置:
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App
將轉化為這些屬性:
environments.dev.url=http://dev.bar.com environments.dev.name=Developer Setup environments.prod.url=http://foo.bar.com environments.prod.name=My Cool App
YAML列表表示如下:
my:
servers:
- dev.bar.com
- foo.bar.com
將轉化為這些屬性:
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
要使用Spring DataBinder實用程式(這是@ConfigurationProperties所做的)繫結到類似的屬性,需要在java.util.List(或Set)型別的目標bean中擁有一個屬性,並且需要提供一個setter,或者用可變值初始化它,例如 這將繫結到上面的屬性:
@ConfigurationProperties(prefix="my") public class Config { private List<String> servers = new ArrayList<String>(); public List<String> getServers() { return this.servers; } }
注:配置列表時需要格外小心,因為覆蓋將無法正常工作。 在上面的示例中,當在多個位置重新定義my.servers時,各個元素的目標是覆蓋,而不是列表。 要確保具有較高優先順序的PropertySource可以覆蓋列表,需要將其定義為單個屬性:
my:
servers: dev.bar.com,foo.bar.com
2. 在Spring Environment中暴露YAML作為屬性
YamlPropertySourceLoader類可用於在Spring環境中將YAML暴露為PropertySource。 這允許使用熟悉的@Value註釋和佔位符語法來訪問YAML屬性。
3. 多個YAML文件
可以使用spring.profiles屬性在單個檔案中指定多個配置檔案的YAML文件,以指示文件何時可以使用。 例如:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120
在上面的示例中,如果開發配置檔案處於active狀態,則server.address屬性將為127.0.0.1。 如果未啟用開發和生產配置檔案,則屬性的值將為192.168.1.100。
如果在應用程式上下文啟動時沒有顯式活動,則啟用預設配置檔案。 因此,在此YAML中,我們為security.user.password設定了一個值,該值僅在“預設”配置檔案中可用:
server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak
而在此示例中,始終設定密碼,因為它未附加到任何配置檔案,並且必須在必要時在所有其他配置檔案中顯式重置:
server:
port: 8000
security:
user:
password: weak
使用“spring.profiles”元素指定的spring profile可以選擇使用 ! 字元否定。 如果為單個文件指定了否定和非否定的配置檔案,則至少一個非否定的配置檔案必須匹配,並且沒有否定的配置檔案可以匹配。
4. YAML的缺點
無法通過@PropertySource註解載入YAML檔案。 因此,如果需要以這種方式載入值,則需要使用屬性檔案(.properties)。
5. 合併YAML列表
任何YAML內容最終都會轉換為屬性。 例如,假設具有名稱和描述屬性的MyPojo物件預設為null。示例:
@ConfigurationProperties("foo")
public class FooProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
考慮以下配置:
foo:
list:
- name: my name
description: my description
---
spring:
profiles: dev
foo:
list:
- name: my another name
如果dev配置檔案未啟用,則FooProperties.list將包含一個如上定義的MyPojo條目。 但是,如果啟用了dev配置檔案,則列表仍將只包含一個條目(名稱為“my another name”,描述為null)。 此配置不會將第二個MyPojo例項新增到列表中,也不會合並專案。
在多個配置檔案中指定集合時,將使用具有最高優先順序的集合(並且僅使用該集合):
foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name
在上面的示例中,考慮到dev配置檔案處於活動狀態,FooProperties.list將包含一個MyPojo條目(名稱為“my another name”,描述為null)。