1. 程式人生 > >SpringBoot(29) - Properties(1) - 外部配置

SpringBoot(29) - Properties(1) - 外部配置

參考:https://docs.spring.io/spring-boot/docs/1.5.17.RELEASE/reference/htmlsingle/#boot-features-external-config

 

Spring Boot允許外部化配置,以便在不同環境中使用相同的應用程式程式碼。 可以使用屬性檔案、YAML檔案、環境變數和命令列引數來外部化配置。可以使用@Value註釋將屬性值直接注入到bean中,通過Spring的Environment抽象訪問或通過@ConfigurationProperties繫結到結構化物件。

Spring Boot使用一個非常特殊的PropertySource命令,旨在允許合理地覆蓋值。 按以下順序考慮屬性:

  • 在使用者目錄上全域性設定屬性(當devtools處於活動狀態時,〜/.spring-boot-devtools.properties)。
  • 測試中的@TestPropertySource註解。
  • 測試中的@SpringBootTest註解的properties屬性。
  • 命令列引數。
  • SPRING_APPLICATION_JSON中的屬性(嵌入在環境變數或系統屬性中的內聯JSON)。
  • ServletConfig初始化引數。
  • ServletContext初始化引數。
  • 來自java:comp/env的JNDI屬性。
  • Java系統屬性(System.getProperties())。
  • 系統環境變數。
  • RandomValuePropertySource的random.*屬性。
  • 打包jar之外的特定於配置檔案的應用程式屬性(application-{profile}.properties和YAML變體)
  • 打包在jar中的特定於配置檔案的應用程式屬性(application-{profile}.properties和YAML變體)
  • 打包jar之外的應用程式屬性(application.properties和YAML變體)。
  • 打包在jar中的應用程式屬性(application.properties和YAML變體)。
  • @Configuration類上的@PropertySource註解。
  • 預設屬性(使用SpringApplication.setDefaultProperties指定)。

為了提供一個具體的例子,假設開發了一個使用name屬性的@Component:

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {
    @Value("${name}")
    private String name;
    // ...
}

在應用程式類路徑上(例如在jar中),可以通過application.properties提供name屬性值。 在新環境中執行時,可以在jar之外提供覆蓋名稱的application.properties; 對於一次性測試,可以使用特定的命令列開關啟動(例如java -jar app.jar --name =“Spring”)。

注:可以在命令列上使用環境變數提供SPRING_APPLICATION_JSON屬性。 例如在UN * X shell中:

$ SPRING_APPLICATION_JSON ='{"foo":{"bar":"spam"}}' java -jar myapp.jar

在此示例中,將在Spring環境中使用foo.bar = spam。 還可以在System變數中將JSON作為spring.application.json提供:

$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar

或者命令上引數:

$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'

或一個JNDI變數:

java:comp/env/spring.application.json

 

1. 配置隨機數

RandomValuePropertySource對於注入隨機值(例如祕鑰或測試用例)非常有用。 它可以產生整數,長整數,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]}

random.int *語法是OPEN value (,max)CLOSE,其中OPEN、CLOSE是任何字元,value和max是整數。 如果提供max引數,則value是最小值,max是最大值(不包括max)。

 

2. 訪問命令列引數

預設情況下,SpringApplication會將任何命令列選項引數(以' - '開頭,例如--server.port = 9000)轉換為屬性並將其新增到Spring Environment中。 如上所述,命令列屬性優先於其他屬性源。

如果不希望將命令列屬性新增到Environment中,可以使用SpringApplication.setAddCommandLineProperties(false)禁用它們。

 

3. Application屬性檔案

SpringApplication將從以下位置的application.properties檔案載入屬性,並將它們新增到Spring環境中:

  • 當前目錄下的/config子目錄
  • 當前目錄
  • classpath下的/config包
  • classpath根目錄

列表按優先順序排序(在列表中較高位置定義的屬性將覆蓋在較低位置中定義的屬性)。可以使用YAML(.yml)檔案替代.properties檔案。

如果不喜歡application.properties作為配置檔名,則可以通過指定spring.config.name環境屬性來切換到另一個。 還可以使用spring.config.location環境屬性(以逗號分隔的目錄位置列表或檔案路徑)來顯式的引用位置。

$ java -jar myproject.jar --spring.config.name=myproject

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

注:spring.config.name和spring.config.location很早就用來確定必須載入哪些檔案,因此必須將它們定義為環境屬性(通常是OS env,系統屬性或命令列引數)。

如果spring.config.location包含目錄(而不是檔案),則它們應該以/結尾(並且在載入之前將附加從spring.config.name生成的名稱,包括特定於配置檔案的檔名)。 spring.config.location中指定的檔案按原樣使用,不支援特定於配置檔案的變體,並且將被任何特定於配置檔案的屬性覆蓋。

以相反的順序搜尋配置位置。 預設情況下,配置的位置是classpath:/,classpath:/config/,file:/,file:./config/。 生成的搜尋順序為:

  • file:./config/
  • file:./
  • classpath:/config/
  • classpath:/

配置自定義配置位置時,除預設位置外,還會使用它們。 在預設位置之前搜尋自定義位置。 例如,如果配置了自定義位置classpath:/custom-config/,file:./custom-config/,則搜尋順序將變為:

  • file:./customer-config/
  • classpath:custom-config/
  • file:./config/
  • file:./
  • classpath:/config/
  • classpath:/

此搜尋順序允許在一個配置檔案中指定預設值,然後有選擇地覆蓋另一個配置檔案中的值。 可以在application.properties(或使用spring.config.name選擇的任何其他基本名稱)中的某個預設位置為應用程式提供預設值。 然後,可以在執行時使用位於其中一個自定義位置的不同檔案覆蓋這些預設值。

注:

  • 如果使用環境變數而不是系統屬性,則大多數作業系統都不允許使用句點分隔的key,但可以使用下劃線(例如SPRING_CONFIG_NAME而不是spring.config.name)。
  • 如果在容器中執行,則可以使用JNDI屬性(在java:comp/env中)或servlet上下文初始化引數來代替環境變數或系統屬性。

 

4. 特定於配置檔案的屬性

除了application.properties檔案之外,還可以使用命名約定application-{profile}.properties定義特定於配置檔案的屬性。 環境具有一組預設配置檔案(預設情況下為[預設]),如果未設定活動配置檔案,則使用這些配置檔案(即,如果未顯式啟用配置檔案,則載入application-default.properties中的屬性)。

特定於配置檔案的屬性從與標準application.properties相同的位置載入,特定於配置檔案的檔案始終覆蓋非特定的檔案,而不管特定於配置檔案的檔案是在打包的jar內部還是外部。

如果指定了多個配置檔案,則應用最後獲勝策略。 例如,spring.profiles.active屬性指定的配置檔案是在通過SpringApplication API配置的配置檔案之後新增的,因此優先。

注:如果在spring.config.location中指定了任何檔案,則不會考慮這些檔案的特定於配置檔案的變體。 如果您還想使用特定於配置檔案的屬性,請使用spring.config.location中的目錄。

 

5. 屬性中的佔位符

application.properties中的值在使用時會通過現有環境進行過濾,因此您可以返回先前定義的值(例如,來自系統屬性)。

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

注:您還可以使用此技術建立現有Spring Boot屬性的“簡短”變體。 有關詳細資訊,請參見第72.4節“使用'短'命令列引數”操作方法。