加載 property 順序
Spring Boot 加載 property 順序如下:
- Devtools 全局配置 (當 devtools 被激活
\~/.spring-boot-devtools.properties). - 測試環境中的
@TestPropertySource注解配置 - 測試環境中的屬性
properties:@SpringBootTest和 測試注解. - 命令行參數
SPRING_APPLICATION_JSON屬性ServletConfig初始化參數ServletContext初始化參數- JNDI attributes from 通過
java:comp/env配置的 JNDI 屬性 - Java 系統屬性 (
System.getProperties()) - 操作系統環境比那里
RandomValuePropertySource加載random.*形式的屬性- jar 包外的
application-{profile}.properties或application-{profile}.yml配置 - jar 包內的
application-{profile}.properties或application-{profile}.yml配置 - jar 包外的
application.properties或application.yml配置 - jar 包內的
application.properties或application.yml配置 @PropertySource綁定的配置- 默認屬性 (通過
SpringApplication.setDefaultProperties指定)
隨機屬性
RandomValuePropertySource 類用於配置隨機值。
示例:
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]}
命令行屬性
默認情況下, SpringApplication 會獲取 -- 參數(例如 --server.port=9000 ),並將這個 property 添加到 Spring 的 Environment 中。
如果不想加載命令行屬性,可以通過 SpringApplication.setAddCommandLineProperties(false) 禁用。
Application 屬性文件
SpringApplication 會自動加載以下路徑下的 application.properties 配置文件,將其中的屬性讀到 Spring 的 Environment 中。
- 當前目錄的
/config子目錄 - 當前目錄
- classpath 路徑下的
/configpackage - classpath 根路徑
注:
以上列表的配置文件會根據順序,后序的配置會覆蓋前序的配置。
你可以選擇 YAML(yml) 配置文件替換 properties 配置文件。
如果不喜歡 application.properties 作為配置文件名,可以使用 spring.config.name 環境變量替換:
$ java -jar myproject.jar --spring.config.name=myproject
可以使用 spring.config.location 環境變量指定配置文件路徑:
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Profile 特定屬性
如果定義 application-{profile}.properties 形式的配置文件,將被視為 profile 環境下的特定配置。
可以通過 spring.profiles.active 參數來激活 profile,如果沒有激活的 profile,默認會加載 application-default.properties 中的配置。
屬性中的占位符
application.properties 中的值會被 Environment 過濾,所以,可以引用之前定義的屬性。
app.name=MyApp
app.description=${app.name} is a Spring Boot application
注:你可以使用此技術來創建 Spring Boot 屬性變量。請參考: Section 77.4, “Use ‘Short’ Command Line Arguments
YAML 屬性
Spring Framework provides two convenient classes that can be used to load YAML documents. The YamlPropertiesFactoryBean loads YAML as Properties and the YamlMapFactoryBean loads YAML as a Map.
Spring 框架有兩個類支持加載 YAML 文件。
YamlPropertiesFactoryBean將 YAML 文件的配置加載為Properties。YamlMapFactoryBean將 YAML 文件的配置加載為Map。
示例 1
environments:
dev:
url: http://dev.example.com
name: Developer Setup
prod:
url: http://another.example.com
name: My Cool App
等價於:
environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App
YAML 支持列表形式,等價於 property 中的 [index] :
my:
servers:
- dev.example.com
- another.example.com
等價於
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
訪問屬性
YamlPropertySourceLoader 類會將 YAML 配置轉化為 Spring Environment 類中的 PropertySource 。然后,你可以如同 properties 文件中的屬性一樣,使用 @Value 注解來訪問 YAML 中配置的屬性。
多 profile 配置
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
YAML 的缺點
注:YAML 注解中的屬性不能通過 @PropertySource 注解來訪問。所以,如果你的項目中使用了一些自定義屬性文件,建議不要用 YAML。
屬性前綴
package com.example;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix="acme")
public class AcmeProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() { ... }
public void setEnabled(boolean enabled) { ... }
public InetAddress getRemoteAddress() { ... }
public void setRemoteAddress(InetAddress remoteAddress) { ... }
public Security getSecurity() { ... }
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() { ... }
public void setUsername(String username) { ... }
public String getPassword() { ... }
public void setPassword(String password) { ... }
public List<String> getRoles() { ... }
public void setRoles(List<String> roles) { ... }
}
}
相當於支持配置以下屬性:
acme.enabledacme.remote-addressacme.security.usernameacme.security.passwordacme.security.roles
然后,你需要使用 @EnableConfigurationProperties 注解將屬性類注入配置類中。
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
屬性松散綁定規則
Spring Boot 屬性名綁定比較松散。
以下屬性 key 都是等價的:
| Property | Note |
|---|---|
acme.my-project.person.first-name |
- 分隔 |
acme.myProject.person.firstName |
駝峰命名 |
acme.my_project.person.first_name |
_ 分隔 |
ACME_MYPROJECT_PERSON_FIRSTNAME |
大寫字母 |
屬性轉換
如果需要類型轉換,你可以提供一個 ConversionService bean (一個名叫 conversionService 的 bean) 或自定義屬性配置 (一個 CustomEditorConfigurer bean) 或自定義的 Converters (被 @ConfigurationPropertiesBinding 注解修飾的 bena)。
時間單位轉換
Spring 使用 java.time.Duration 類代表時間大小,以下場景適用:
- 除非指定
@DurationUnit,否則一個 long 代表的時間為毫秒。 - ISO-8601 標准格式(
java.time.Duration的實現就是參照此標准) - 你也可以使用以下支持的單位:
ns- 納秒us- 微秒ms- 毫秒s- 秒m- 分h- 時d- 天
示例:
@ConfigurationProperties("app.system")
public class AppSystemProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
public Duration getSessionTimeout() {
return this.sessionTimeout;
}
public void setSessionTimeout(Duration sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public Duration getReadTimeout() {
return this.readTimeout;
}
public void setReadTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
}
}
數據大小轉換
Spring 使用 DataSize 類代表數據大小,以下場景適用:
- long 值(默認視為 byte)
- 你也可以使用以下支持的單位:
BKBMBGBTB
示例:
@ConfigurationProperties("app.io")
public class AppIoProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
public DataSize getBufferSize() {
return this.bufferSize;
}
public void setBufferSize(DataSize bufferSize) {
this.bufferSize = bufferSize;
}
public DataSize getSizeThreshold() {
return this.sizeThreshold;
}
public void setSizeThreshold(DataSize sizeThreshold) {
this.sizeThreshold = sizeThreshold;
}
}
校驗屬性
@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// ... getters and setters
public static class Security {
@NotEmpty
public String username;
// ... getters and setters
}
}
你也可以自定義一個名為 configurationPropertiesValidator 的校驗器 Bean。獲取這個 @Bean 的方法必須聲明為 static。
示例源碼
示例源碼:spring-boot-property
