屬性與配置
本節包含關於設定和讀取屬性與配置設定及其與 Spring Boot 應用互動的主題。
在構建時自動展開屬性
與其硬編碼專案構建配置中已指定的某些屬性,不如使用現有的構建配置來自動展開它們。這在 Maven 和 Gradle 中都是可能的。
使用 Maven 自動展開屬性
你可以使用資源過濾來在 Maven 專案中自動展開屬性。如果你使用 spring-boot-starter-parent
,那麼你可以透過 @..@
佔位符引用你的 Maven ‘專案屬性’,示例如下
-
屬性
-
YAML
app:
encoding: "@project.build.sourceEncoding@"
java:
version: "@java.version@"
只有生產配置會以這種方式被過濾(換句話說,src/test/resources 不會應用過濾)。 |
如果你啟用 addResources 標誌,spring-boot:run goal 可以直接將 src/main/resources 新增到 classpath(用於熱過載)。這樣做會繞過資源過濾和此功能。你可以轉而使用 exec:java goal 或自定義外掛配置。更多詳情請參閱外掛使用頁面。 |
如果你不使用 starter parent,你需要在 pom.xml
的 <build/>
元素內包含以下元素
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
你還需要在 <plugins/>
內包含以下元素
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
如果你在配置中使用標準的 Spring 佔位符(例如 ${placeholder} ),useDefaultDelimiters 屬性很重要。如果該屬性未設定為 false ,這些佔位符可能會被構建過程展開。 |
使用 Gradle 自動展開屬性
你可以透過配置 Java 外掛的 processResources
任務來自動展開 Gradle 專案中的屬性,示例如下
tasks.named('processResources') {
expand(project.properties)
}
然後你可以透過使用佔位符引用你的 Gradle 專案屬性,示例如下
-
屬性
-
YAML
app.name=${name}
app.description=${description}
app:
name: "${name}"
description: "${description}"
Gradle 的 expand 方法使用 Groovy 的 SimpleTemplateEngine ,它會轉換 ${..} 標記。${..} 樣式與 Spring 自身的屬性佔位符機制衝突。要同時使用 Spring 屬性佔位符和自動展開,請按如下方式轉義 Spring 屬性佔位符:\${..} 。 |
外部化 SpringApplication 的配置
一個 SpringApplication
具有 bean 屬性 setter,因此你可以在建立應用時使用其 Java API 來修改其行為。或者,你可以透過在 spring.main.*
中設定屬性來外部化配置。例如,在 application.properties
中,你可能有以下設定
-
屬性
-
YAML
spring.main.web-application-type=none
spring.main.banner-mode=off
spring:
main:
web-application-type: "none"
banner-mode: "off"
這樣,Spring Boot banner 在啟動時將不會列印,並且應用不會啟動嵌入式 Web 伺服器。
外部配置中定義的屬性會覆蓋和替換使用 Java API 指定的值,但主要源(primary sources)是值得注意的例外。主要源是提供給 SpringApplication
建構函式的那些源
-
Java
-
Kotlin
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
import org.springframework.boot.Banner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
object MyApplication {
@JvmStatic
fun main(args: Array<String>) {
val application = SpringApplication(MyApplication::class.java)
application.setBannerMode(Banner.Mode.OFF)
application.run(*args)
}
}
或者提供給 SpringApplicationBuilder
的 sources(…)
方法
-
Java
-
Kotlin
import org.springframework.boot.Banner;
import org.springframework.boot.builder.SpringApplicationBuilder;
public class MyApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.sources(MyApplication.class)
.run(args);
}
}
import org.springframework.boot.Banner
import org.springframework.boot.builder.SpringApplicationBuilder
object MyApplication {
@JvmStatic
fun main(args: Array<String>) {
SpringApplicationBuilder()
.bannerMode(Banner.Mode.OFF)
.sources(MyApplication::class.java)
.run(*args)
}
}
考慮到上面的示例,如果我們的配置如下
-
屬性
-
YAML
spring.main.sources=com.example.MyDatabaseConfig,com.example.MyJmsConfig
spring.main.banner-mode=console
spring:
main:
sources: "com.example.MyDatabaseConfig,com.example.MyJmsConfig"
banner-mode: "console"
實際應用將顯示 banner(被配置覆蓋),併為 ApplicationContext
使用三個源。應用源是
-
MyApplication
(來自程式碼) -
MyDatabaseConfig
(來自外部配置) -
MyJmsConfig
(來自外部配置)
更改應用外部屬性的位置
預設情況下,來自不同源的屬性會按照定義的順序新增到 Spring Environment
中(確切順序請參閱“Spring Boot 特性”部分中的外部化配置)。
你也可以提供以下系統屬性(或環境變數)來改變行為
-
spring.config.name
(SPRING_CONFIG_NAME
): 預設為application
作為檔名的根。 -
spring.config.location
(SPRING_CONFIG_LOCATION
): 要載入的檔案(例如 classpath 資源或 URL)。會為此文件設定一個單獨的Environment
屬性源,它可以被系統屬性、環境變數或命令列覆蓋。
無論你在環境中設定了什麼,Spring Boot 總是會像上面描述的那樣載入 application.properties
。預設情況下,如果使用 YAML,那麼副檔名為 ‘.yaml’ 和 ‘.yml’ 的檔案也會被新增到列表中。
如果你想獲取關於正在載入檔案的詳細資訊,你可以將 org.springframework.boot.context.config 的日誌級別設定為 trace 。 |
使用‘簡短’命令列引數
有些人喜歡使用(例如)--port=9000
而不是 --server.port=9000
來在命令列上設定配置屬性。你可以透過在 application.properties
中使用佔位符來啟用此行為,示例如下
-
屬性
-
YAML
server.port=${port:8080}
server:
port: "${port:8080}"
如果你繼承了 spring-boot-starter-parent POM,則 maven-resources-plugins 的預設過濾標記已從 ${*} 更改為 @ (即 @maven.token@ 而不是 ${maven.token} ),以防止與 Spring 樣式的佔位符衝突。如果你直接為 application.properties 啟用了 Maven 過濾,你可能還需要更改預設過濾標記以使用其他分隔符。 |
在這種特定情況下,埠繫結在 Heroku 或 Cloud Foundry 等 PaaS 環境中是有效的。在這兩個平臺上,PORT 環境變數會自動設定,並且 Spring 可以繫結到 Environment 屬性的大寫同義詞。 |
使用 YAML 作為外部屬性
YAML 是 JSON 的超集,因此,它是一種方便的語法,用於以層次結構格式儲存外部屬性,示例如下
spring:
application:
name: "cruncher"
datasource:
driver-class-name: "com.mysql.jdbc.Driver"
url: "jdbc:mysql:///test"
server:
port: 9000
建立一個名為 application.yaml
的檔案,並將其放在 classpath 的根目錄。然後將 snakeyaml
新增到你的依賴項中(Maven 座標為 org.yaml:snakeyaml
,如果你使用 spring-boot-starter
則已包含)。YAML 檔案會被解析為 Java Map<String,Object>
(類似於 JSON 物件),Spring Boot 會展平該 Map,使其深度為一層,並使用句點分隔的鍵,就像許多人在 Java 中習慣使用 Properties
檔案一樣。
前面的 YAML 示例對應於以下 application.properties
檔案
spring.application.name=cruncher
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///test
server.port=9000
有關 YAML 的更多資訊,請參閱“Spring Boot 特性”部分中的使用 YAML。
設定活動的 Spring Profile
Spring Environment
有一個 API 用於此,但你通常會設定一個系統屬性(spring.profiles.active
)或一個作業系統環境變數(SPRING_PROFILES_ACTIVE
)。此外,你還可以使用 -D
引數啟動你的應用(記住將其放在主類或 jar 包之前),如下所示
$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar
在 Spring Boot 中,你也可以在 application.properties
中設定活動的 profile,示例如下
-
屬性
-
YAML
spring.profiles.active=production
spring:
profiles:
active: "production"
以這種方式設定的值會被系統屬性或環境變數設定替換,但不會被 SpringApplicationBuilder.profiles()
方法替換。因此,後者 Java API 可用於增加 profile,而無需更改預設設定。
更多資訊請參閱“Spring Boot 特性”部分中的Profile。
設定預設 Profile 名稱
預設 profile 是在沒有其他 profile 活動時啟用的 profile。預設情況下,預設 profile 的名稱是 default
,但可以使用系統屬性(spring.profiles.default
)或作業系統環境變數(SPRING_PROFILES_DEFAULT
)進行更改。
在 Spring Boot 中,你也可以在 application.properties
中設定預設 profile 名稱,示例如下
-
屬性
-
YAML
spring.profiles.default=dev
spring:
profiles:
default: "dev"
更多資訊請參閱“Spring Boot 特性”部分中的Profile。
根據環境更改配置
Spring Boot 支援多文件 YAML 和 Properties 檔案(詳情請參閱使用多文件檔案),它們可以根據活動的 profile 有條件地啟用。
如果文件包含 spring.config.activate.on-profile
鍵,則 profile 值(逗號分隔的 profile 列表或 profile 表示式)將被傳遞給 Spring 的 Environment.acceptsProfiles()
方法。如果 profile 表示式匹配,則該文件將被包含在最終合併中(否則不會),示例如下
-
屬性
-
YAML
server.port=9000
#---
spring.config.activate.on-profile=development
server.port=9001
#---
spring.config.activate.on-profile=production
server.port=0
server:
port: 9000
---
spring:
config:
activate:
on-profile: "development"
server:
port: 9001
---
spring:
config:
activate:
on-profile: "production"
server:
port: 0
在前面的示例中,預設埠是 9000。但是,如果名為“development”的 Spring profile 活動,則埠為 9001。如果“production”活動,則埠為 0。
文件按照遇到的順序合併。後面的值會覆蓋前面的值。 |
發現外部屬性的內建選項
Spring Boot 在執行時將來自 application.properties
(或 YAML 檔案及其他位置)的外部屬性繫結到應用中。沒有(技術上也不可能有)在單一位置列出所有支援屬性的完整列表,因為貢獻可能來自 classpath 上的額外 jar 檔案。
具有 Actuator 特性的正在執行的應用有一個 configprops
端點,該端點顯示所有透過 @ConfigurationProperties
可用的已繫結和可繫結屬性。
附錄包含一個 application.properties
示例,其中列出了 Spring Boot 支援的大部分常用屬性。確切的列表可以透過搜尋原始碼中的 @ConfigurationProperties
和 @Value
註解以及偶爾使用 Binder
來獲取。有關載入屬性的確切順序,請參閱外部化配置。