SpringBoot 教程之屬性加載詳解

加載 property 順序

Spring Boot 加載 property 順序以下:html

  1. Devtools 全局配置 (當 devtools 被激活 ~/.spring-boot-devtools.properties).
  2. 測試環境中的 @TestPropertySource 註解配置
  3. 測試環境中的屬性 properties@SpringBootTest測試註解.
  4. 命令行參數
  5. SPRING_APPLICATION_JSON 屬性
  6. ServletConfig 初始化參數
  7. ServletContext 初始化參數
  8. JNDI attributes from 經過 java:comp/env 配置的 JNDI 屬性
  9. Java 系統屬性 (System.getProperties())
  10. 操做系統環境比那裏
  11. RandomValuePropertySource 加載 random.* 形式的屬性
  12. jar 包外的 application-{profile}.propertiesapplication-{profile}.yml 配置
  13. jar 包內的 application-{profile}.propertiesapplication-{profile}.yml 配置
  14. jar 包外的 application.propertiesapplication.yml 配置
  15. jar 包內的 application.propertiesapplication.yml 配置
  16. @PropertySource 綁定的配置
  17. 默認屬性 (經過 SpringApplication.setDefaultProperties 指定)

隨機屬性

RandomValuePropertySource 類用於配置隨機值。java

示例:git

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 中。github

若是不想加載命令行屬性,能夠經過 SpringApplication.setAddCommandLineProperties(false) 禁用。spring

Application 屬性文件

SpringApplication 會自動加載如下路徑下的 application.properties 配置文件,將其中的屬性讀到 Spring 的 Environment 中。api

  1. 當前目錄的 /config 子目錄
  2. 當前目錄
  3. classpath 路徑下的 /config package
  4. classpath 根路徑

注:bash

以上列表的配置文件會根據順序,後序的配置會覆蓋前序的配置。session

你能夠選擇 YAML(yml) 配置文件替換 properties 配置文件。oracle

若是不喜歡 application.properties 做爲配置文件名,可使用 spring.config.name 環境變量替換:app

$ 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

源碼

完整示例:源碼

使用方法:

mvn clean package
cd target
java -jar sbe-core-property.jar
複製代碼

引伸和引用

引伸

參考

相關文章
相關標籤/搜索