加載 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 路徑下的
/config
package - 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.enabled
acme.remote-address
acme.security.username
acme.security.password
acme.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)
- 你也可以使用以下支持的單位:
B
KB
MB
GB
TB
示例:
@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