SpringBoot 教程之屬性加載詳解


加載 property 順序

Spring Boot 加載 property 順序如下:

  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 類用於配置隨機值。

示例:

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

  1. 當前目錄的 /config 子目錄
  2. 當前目錄
  3. classpath 路徑下的 /config package
  4. 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

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM