1. 程式人生 > >SpringBoot入門筆記09——屬性配置檔案詳解以及多環境配置

SpringBoot入門筆記09——屬性配置檔案詳解以及多環境配置

SpringBoot的外部配置

Spring Boot允許將配置外部化(externalize) ,這樣你就能夠在不同的環境下使用相同的程式碼。你可以使用properties檔案,YAML檔案,環境變數和命令列引數來外部化配置。使用@Value註解,可以直接將屬性值注入到beans中,然後通過Spring的 Environment 抽象或通過 @ConfigurationProperties 繫結到結構化物件來
訪問。
Spring Boot設計了一個非常特別的 PropertySource 順序,以允許對屬性值進行合理的覆蓋,屬性會以如下的順序進行設值:

  1. home目錄下的devtools全域性設定屬性( ~/.spring-bootdevtools.properties ,如果devtools啟用) 。

  2. 測試用例上的@TestPropertySource註解。

  3. 測試用例上的@SpringBootTest#properties註解。

  4. 命令列引數

  5. 來自 SPRING_APPLICATION_JSON 的屬性(環境變數或系統屬性中內嵌的內聯JSON) 。

  6. ServletConfig 初始化引數。

  7. ServletContext 初始化引數。

  8. 來自於 java:comp/env 的JNDI屬性。

  9. Java系統屬性(System.getProperties()) 。

  10. 作業系統環境變數。

  11. RandomValuePropertySource,只包含 random.* 中的屬性。

  12. 沒有打進jar包的Profile-specific應用屬性( application-{profile}.properties 和YAML變數) 。

  13. 打進jar包中的Profile-specific應用屬性( application-{profile}.properties 和YAML變數) 。

  14. 沒有打進jar包的應用配置( application.properties 和YAML變數) 。

  15. 打進jar包中的應用配置( application.properties 和YAML變數) 。

  16. @Configuration 類上的 @PropertySource 註解。

  17. 預設屬性(使用 SpringApplication.setDefaultProperties 指定) 。
    下面是具體的示例,假設你開發一個使用name屬性的 @Component :

import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}

你可以將一個 application.properties 放到應用的classpath下,為 name 提供一個合適的預設屬性值。當在新的環境中執行時,可以在jar包外提供一個 application.properties 覆蓋 name 屬性。對於一次性的測試,你可以使用特定的命令列開關啟動應用(比如, java -jar app.jar --name=“Spring” ) 。
注 SPRING_APPLICATION_JSON 屬性可以通過命令列的環境變數設定,例如,在一個UNIX shell中可以這樣:
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar
本示例中,如果是Spring Environment ,你可以以 foo.bar=spam 結尾;如果在一個系統變數中,可以提供作為 spring.application.json 的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

自定義屬性與載入

我們在使用Spring Boot的時候,通常也需要定義一些自己使用的屬性,我們可以如下方式直接定義:

com.text.name.name=姓名
com.text.title=Spring Boot標題

然後通過@Value("${屬性名}")註解來載入對應的配置屬性,具體如下:

@Component
public class BlogProperties {

    @Value("${com.text.name}")
    private String name;
    @Value("${com.text.title}")
    private String title;

    // 省略getter和setter

}

引數間的引用

application.properties中的各個引數之間也可以直接引用來使用,就像下面的設定:

web.upload-path=D:/images
spring.resources.static-locations=classpath:file:${web.upload-path}

spring.resources.static-locations引數引用了上文中定義的web.upload-path屬性

使用隨機數

在一些情況下,有些引數我們需要希望它不是一個固定的值,比如金鑰、服務埠等。Spring Boot的屬性配置檔案中可以通過${random}來產生int值、long值或者string字串,來支援屬性的隨機值。

//隨機字串
my.secret=${random.value}
//隨機int
my.number=${random.int}
//隨機long
my.bignumber=${random.long}
//10以內的隨機數
my.number.less.than.ten=${random.int(10)}
//1024--65535
my.number.in.range=${random.int[1024,65536]}

random.int* 語法是 OPEN value (,max) CLOSE ,此處 OPEN,CLOSE 可以是任何字元,並且 value,max 是整數。如果提供 max ,那麼 value 是最小值, max 是最大值(不包含在內) 。

通過命令列設定屬性值

預設情況下, SpringApplication 會將所有命令列配置引數(以’–'開頭,比如 --server.port=9000 ) 轉化成一個 property ,並將其新增到SpringEnvironment 中。連續的兩個減號--就是對application.properties中的屬性值進行賦值的標識。正如以上章節提過的,命令列屬性總是優先於其他屬性源。

通過命令列來修改屬性值固然提供了不錯的便利性,但是通過命令列就能更改應用執行的引數,那豈不是很不安全?是的,所以Spring Boot也貼心的提供了遮蔽命令列訪問屬性的設定,只需要這句設定就能遮蔽:SpringApplication.setAddCommandLineProperties(false)

多環境配置

SpringApplication 將從以下位置載入 application.properties 檔案,並把
它們新增到Spring Environment 中:

  1. 當前目錄下的 /config 子目錄。
  2. 當前目錄。
  3. classpath下的 /config 包。
  4. classpath根路徑(root) 。
    該列表是按優先順序排序的(列表中位置高的路徑下定義的屬性將覆蓋位置低的) 。

我們在開發Spring Boot應用時,通常同一套程式會被應用和安裝到幾個不同的環境,比如:開發、測試、生產等。其中每個環境的資料庫地址、伺服器埠等等配置都會不同,如果在為不同環境打包時都要頻繁修改配置檔案的話,那必將是個非常繁瑣且容易發生錯誤的事。

對於多環境的配置,各種專案構建工具或是框架的基本思路是一致的,通過配置多份不同環境的配置檔案,再通過打包命令指定需要打包的內容之後進行區分打包,Spring Boot也不例外,或者說更加簡單。

在Spring Boot中多環境配置檔名需要滿足application-{profile}.properties的格式,其中{profile}對應你的環境標識,比如:

  • application-dev.properties:開發環境
  • application-test.properties:測試環境
  • application-prod.properties:生產環境

至於哪個具體的配置檔案會被載入,需要在application.properties檔案中通過spring.profiles.active屬性來設定,其值對應{profile}值。

如:spring.profiles.active=test就會載入application-test.properties配置檔案內容

下面,以不同環境配置不同的服務埠為例,進行樣例實驗。

  • 針對各環境新建不同的配置檔案application-dev.propertiesapplication-test.propertiesapplication-prod.properties
  • 在這三個檔案均都設定不同的server.port屬性,如:dev環境設定為1111,test環境設定為2222,prod環境設定為3333
  • application.properties中設定spring.profiles.active=dev,就是說預設以dev環境設定
  • 測試不同配置的載入
    • 執行java -jar xxx.jar,可以觀察到服務埠被設定為1111,也就是預設的開發環境(dev)
    • 執行java -jar xxx.jar --spring.profiles.active=test,可以觀察到服務埠被設定為2222,也就是測試環境的配置(test)
    • 執行java -jar xxx.jar --spring.profiles.active=prod,可以觀察到服務埠被設定為3333,也就是生產環境的配置(prod)

按照上面的實驗,可以如下總結多環境的配置思路:

  • application.properties中配置通用內容,並設定spring.profiles.active=dev,以開發環境為預設配置
  • application-{profile}.properties中配置各個環境不同的內容
  • 通過命令列方式去啟用不同環境的配置