Spring Boot外部配置

外部配置(Externalized Configuration)

來源於spring boot官方文檔的簡單筆記,寫的比較亂,大體上是作爲簡單的梳理,回過頭來看的,或者快速查找目錄使用,詳細的還是要看官方文檔

配置屬性讀取順序爲:

  1. devtools global settings properties,位置~/.spring-boot-devtools.properties
  2. @TestPropertySource
  3. 測試的properties屬性,包含@SpringBootTest和其他的測試註解
  4. 命令行參數(command line argument)
  5. SPRING_APPLICATION_JSON獲取的屬性
  6. ServletConfig初始化參數
  7. ServletContext初始化參數
  8. JNDI屬性,從java:comp/dev
  9. java系統屬性(System.getProperties())
  10. 系統環境變量
  11. RandomValuePropertySource中random.*的值
  12. jar包外指定的應用屬性,application-{profile}.properties以及YAML變量
  13. jar包內的指定的應用屬性,application-{profile}.properties以及YAML變量
  14. jar包外的application.properties配置或者YAML
  15. jar包內的application.properties
  16. 在@Configuration註解類上配置的@PropertySource註解配置
  17. 默認屬性(通過SpringApplication.setDefaultProperties)

配置隨機值(Configuring Random Values)

RandomValuePropertySource對於屬性設置隨機值非常方便,包含了integers,longs,uuid,strings等等隨機值

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]}

其中對於int或者long等(是開口,不包含,[包含。

獲取命令行屬性(Accessing Command Line Properties)

在命令行啓動時,可以通過使用--前綴標誌屬性,比如--server.port=9000,可以添加到spring的environment中,可以通過SpringApplication.setAddCommandLineProperties(false)禁用。

應用屬性文件(Application Property Files)

SpringApplication從以下順序位置讀取application.properties文件中的屬性到Spring Environment:

  • 當前目錄的/config
  • 當前目錄
  • classpath下面的/config包
  • classpath的根路徑
    當然了,也是可以支持YAML(.yml)文件。
    如果不想使用application.properties名字,可以通過使用spring.config.name指定文件名,通過spring.config.location指定讀取的路徑(多個路徑使用逗號隔開)。
    如果路徑中包含目錄的話,注意需要/結尾,通過這個路徑直接拼接上name指定的名字。
    注意,配置路徑的搜索順序是反着來的,也就是說,如果配置了多個路徑的話後面的路徑的排在前面優先級。
    也可以通過spring.config.additional-location配置的搜索路徑,在默認路徑之前搜索。

指定環境屬性(Profile-specific Properties)

除了application.properties文件,還有可以指定環境屬性配置文件,約定的規則是:application-{profile}.properties。默認的是default,也就是說沒有指定的話就是導入application-default.properties。該文件如果有的話,會優先於application.properties配置。
對於指定了多個spring.profiles.active,以最後一個生效。
注意:spring.config.location指定了,那麼直接在該位置搜索配置,profile-specific變量就不會考慮了。

屬性佔位符(Placeholders in Properties)

application.properties文件中的屬性使用時會通過Environment中存在的值過濾,也就是說,反過來,配置文件中的屬性值可以使用Environment中的屬性。

app.name=App
app.description=${app.name} is a Spring Boot application

加密屬性(Encrypting Properties)

Spring Boot對於加密屬性值沒有提供內建的支持,但是對於修改Environment中的屬性值提供了鉤子(hook),EnvironmentPostProcessor接口可以操作屬性中的值,也就是說Evironment中的屬性加載完成以後會先執行EnvironmentPostProcessor接口中的方法,然後再啓動應用。
對於Spring Cloud Vault中有相關的處理,有興趣可以查看一下。

使用YAML代替屬性(Using YAML Instead of Properties)

YAML是JSON格式的超類,結構化的樣式配置數據。對於YAML格式簡單點說就是一般以.yml結尾的配置文件,通過縮進的方式配置屬性。SpringApplication是自動支持YAML的,在spring-boot-starter中是包含了SnakeYAML庫的。
Spring框架有YamlPropertiesFactoryBean讀取YAML爲Properties,YamlMapFactoryBean導入YAML爲一個Map。

environments:
	dev:
		url: https://dev.example.com
		name: Developer Setup
	prod:
		url: https://another.example.com
		name: My Cool App

等效於:

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

對於數組類型的:

my:
 servers:
  - dev.example.com
  - another.example.com

//等效於
my.servers[0]=dev.example.com
my.servers[1]=another.example.com

對於數據的綁定,數組的話可以使用List或者Set,需要提供一個setter方法或者初始化爲一個可變的值。可以通過@ConfigurationProperties註解自動注入。

@ConfigurationProperties(prefix="my")
public class Config {
	private List<String> servers = new ArrayList<String>();
	public List<String> getServers() {
	return this.servers;
	}
}

可以通過YamlPropertySourceLoader將YAML文件作爲PropertySource到Spring的Environment中。這樣的話可以使用@Value作爲佔位符語法。

多環境YAML文檔(Multi-profile YAML Documents)

在YAML當個文檔中,可以通過spring.profiles鍵來標誌配置的激活環境:

server:
 address: 192.168.1.100
---
spring:
 profiles: development
server:
 address: 127.0.0.1
---
spring:
 profiles: production & eu-central   # 此處是表達式語法
server:
 address: 192.168.1.120

如上示例所示,沒有指定profiles的爲默認狀態。

類型安全的配置屬性(Type-safe Configuration Properties)

使用@Value("${property}")注入屬性值,遇到需要注入的變量太多的時候,就比較繁瑣,這個使用SpringBoot提供@ConfigurationProperties註解快速注入屬性,上一小節也有使用示例。通過@ConfigurationProperties(prefix="")的方式之前前綴,然後就會自動將環境中這種對象的前綴加上變量拼接的屬性中匹配,找到的話就將值設置到使用該註解的對象中。
注意:Getters和Setters通常是必要的,因爲屬性自動綁定是通過標準的java bean屬性描述,和Spring MVC相似。在以下場景中,可以不需要setter:

  • Maps,只要初始化以後,需要getter方法,不需要setter了,因爲可以被綁定器修改(can be mutated by the binder)。
  • Collections以及數組可以通過索引(典型的是YAML)或者通過單箇中間使用逗號隔開的值注入。後者setter方法是必須的,我們建議是最好都加上setter方法。如果集合初始化了,確保是可變的。
  • 對於內部的一個初始化了的POJO屬性,不需要setter。如果你想使用默認構造器創建實例,需要setter方法(if you want to the binder to create the instance on the fly by using its default constructor,you need a setter)。
  • 有些人使用Lombok自動添加getters以及setters,確保Lombok對於這些類型不生成特別的構造器,因爲容器會自動使用這些構造器初始化對象。
  • 最後,該方式只支持標準java bean屬性,綁定到靜態屬性中是不支持的。

對於觸發該註解的方式有兩種,一種是在配置類中使用@EnableConfigurationProperties(AcmeProperties.class),標明AcmeProperties類需要自動注入屬性,也可以直接標明需要注入類爲Spring的一個組件,比如@Component,@Bean之類的。

@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}

@Component
@ConfigurationProperties(prefix="acme")
public class AcmeProperties {
// ... see the preceding example
}

@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
...
}

對於屬性前綴這種自動配置方式,spring提供了更加寬鬆話的匹配規則,比如說大小寫差別,駝峯,中間加-等標記,具體可以到文檔中查看,針對.properties,.yml,environment,系統屬性等等,有一點點差別。但是如果不是特殊情況還是不建議差別太大。

在屬性自動裝配時,spring會自動往正確的類型轉換,如果需要自定義的話,可以提供ConversionService或者定製屬性編輯器(通過CustomEditorConfigurer對象)或者定製轉換器Converters(使用@ConfigurationPropertiesBinding註解標註)

對於自動轉換的屬性變量,可以使用註解指定單位之類的,比如@DurationUnit(ChronoUnit.SECONDS),@DataSizeUnit(DataUnit.MEGABYTES)等等。

也可以使用@Validated註解使用驗證格式,該註解遵循的是JSR-303

@ConfigurationProperties 和 @Value的區別
其中前一個支持寬鬆綁定(Relaxed binding)以及元數據支持(Meta-data support),後者支持SpEL表達式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章