注意:本 Spring Boot 系列文章基於 Spring Boot 版本 v2.1.1.RELEASE 進行學習分析,版本不同可能會有細微差別。
前言
不管是通過官方提供的方式獲取 Spring Boot 項目,還是通過 IDEA 快速的創建 Spring Boot 項目,我們都會發現在 resource 有一個配置文件 application.properties
,也有可能是application.yml
.這個文件也就是 Spring Boot 的配置文件。
1. YAML 文件
在 Spring Boot
中,官方推薦使用 properties
或者 YAML
文件來完成配置,對於 YAML
文件格式還不了解的可以查看官方的具體格式,這里只做簡單介紹。
YAML 語法規則:
- 大小寫敏感
- 縮進表示層級
- 縮進只能使用空格
- 空格的數量不重要,但是相同層級的元素要左側對齊
#
開頭的行表示注釋
YAML 支持的數據結構:
-
單純的變量,不可再分的單個的值,如數字,字符串等。
name: Darcy age: 12 # ~表示NULL值 email: ~ # 多行字符串可以使用|保留換行符,也可以使用>折疊換行。 # +表示保留文字塊末尾的換行,-表示刪除字符串末尾的換行。 message:|- Hello world
-
數組,一組按次序排列的值。
lang: - java - golang - c # 或者行內寫法 lang:[java,golang,c]
-
對象,鍵值對的集合。
person: name:Darcy age:20 # 或者行內寫法 person:{name:Darcy,age:20}
使用 YAML
支持的三種數據結構通過組合可以形成復雜的復合結構。
# 服務啟動端口號
server:
port: 8080
# 配置person屬性值
person:
last-name: Darcy
age: 20
birth: 2018/01/01
email: gmail@gmail.com
maps:
key1:java
key2:golang
lists:
- a
- b
- c
dog:
name: 旺財
age: 2
需要注意的是 YAML
文件不能使用@PropertySource
加載
2. Properties 文件
properties
配置文件簡單好用,在各種配置環境里都可以看到它的身影,它簡單易用,但是在配置復雜結構時不如 YAML
優雅美觀。同樣拿上面的 YAML
的復合結構舉例,演示同樣的配置在 properties
文件中的寫法。
# 服務啟動端口號
server.port=8080
# 配置屬性值(使用IDE進行配置需要處理編碼問題,不然中文會發送亂碼現象)
person.last-name=張三
person.age=18
person.birth=2018/12/06
person.email=niu@gmail.com
person.maps.key1=c
person.maps.key2=java
person.maps.key3=golang
person.lists=a,b,c,d
person.dog.name=旺財
person.dog.age=1
3. 隨機數與占位符
RandomValuePropertySource
類對於注入隨機值很有用(例如,注入秘密或測試用例)。它可以生成整數,長整數,uuid 或字符串等,通過 Spring Boot 對我們的封裝,我們可以輕松的使用。
占位符允許在配置的值中引用之前定義過的變量。
# 生成隨機值
bootapp.secret=$ {random.value}
bootapp.number=$ {random.int}
bootapp.bignumber=$ {random.long}
bootapp.uuid=$ {random.uuid}
bootapp.number.less.than.ten=$ {random.int(10)}
bootapp.number.in.range=$ {random.int [1024,65536]}
# 屬性的占位符
bootapp.name=SpringBoot
bootapp.description=${bootapp.name}是一個spring應用程序
4. 配置的使用
通過上面的介紹,可以發現不管是使用 YAML
還是 Properties
都可以進行配置文件的編寫,但是還不知道具體的使用方式,通過下面的幾個注解,可以讓我們了解到這些配置的具體使用方式。
在使用配置之前,添加所需依賴。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 導入配置文件處理器,在配置相關文件時候會有提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
4.1 ConfigurationProperties
@ConfigurationProperties
注解是 Spring Boot
提供的一種使用屬性的注入方法。不僅可以方便的把配置文件中的屬性值與所注解類綁定,還支持松散綁定,JSR-303 數據校驗等功能。以上面演示的 Properties
的配置為例演示 @ConfigurationProperties
注解的使用。
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
* @Author niujinpeng
* @Date 2018/12/6 22:54
*/
@Data
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
private String lastName;
private Integer age;
private Date birth;
private Map<String, String> maps;
private List<String> lists;
private Dog dog;
/**
* 支持數據校驗
*/
@Email
private String email;
}
@Data
是 Lombok 的注解,會為這個類所有屬性添加 getting 和 setting 方法,此外還提供了equals、canEqual、hashCode、toString 方法。@Component
自動添加 bean 到 spring 容器中。@ConfigurationProperties
告訴這個類的屬性都是配置文件里的屬性,prefix 指定讀取配置文件的前綴。
4.2 Value
@Value
支持直接從配置文件中讀取值,同時支持 SpEL 表達式,但是不支持復雜數據類型和數據驗證,下面是具體的使用。
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Data
@Component
@Validated
public class PersonValue {
/**
* 直接從配置文件讀取一個值
*/
@Value("${person.last-name}")
private String lastName;
/**
* 支持SpEL表達式
*/
@Value("#{11*4/2}")
private Integer age;
@Value("${person.birth}")
private Date birth;
/**
* 不支持復雜類型
*/
private Map<String, String> maps;
private List<String> lists;
private Dog dog;
/**
* 不支持數據校驗
*/
@Email
@Value("xxx@@@@")
private String email;
}
編寫單元測試代碼測試代碼查看屬性綁定是否成功。
import net.codingme.boot.domain.Person;
import net.codingme.boot.domain.PersonValue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloApplicationTests {
@Autowired
private MockMvc mvc;
@Autowired
private Person person;
@Autowired
private PersonValue personValue;
/**
* 模擬請求測試
*
* @throws Exception
*/
@Test
public void testGetHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string("Greetings from Spring Boot!"));
}
/**
* 測試@ConfigurationProperties
*/
@Test
public void testPersion() {
System.out.println(person);
}
/**
* 測試@Value 引入配置值
*/
@Test
public void testPersionValue() {
System.out.println(personValue);
}
}
運行發現數據已經正常綁定。
通過上面的示例,也可以發現 @ConfigurationProperties
和 @Value
的區別。
特征 | @ConfigurationProperties | @Value |
---|---|---|
功能 | 批量注入配置文件屬性 | 一個一個注入 |
松散綁定(松散的語法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR-303 數據校驗 | 支持 | 不支持 |
復雜類型 | 支持 | 不支持 |
@ConfigurationProperties
和 @Value
的使用場景。
如果說,只是在某個業務邏輯中獲取配置文件的某個值,使用 @Value
.
如果說,專門編寫有一個 Java Bean 來和配置文件映射,使用 @ConfigurationProperties
.
4.3 PropertySource
隨着業務復雜性的增加,配置文件也越來越多,我們會覺得所有的配置都寫在一個 properties 文件會使配置顯得繁雜不利於管理,因此希望可以把映射屬性類的配置單獨的抽取出來。由於 Spring Boot 默認讀取 application.properties
,因此在抽取之后之前單獨的@ConfigurationProperties(prefix = "person")
已經無法讀取到信息。這是可以使用 @PropertySource
注解來指定要讀取的配置文件。
需要注意的是,使用 @PropertySource
加載自定義的配置文件,,由於 @PropertySource
指定的文件會優先加載,所以如果在 applocation.properties
中存在相同的屬性配置,會覆蓋前者中對於的值。
如果抽取 person
配置為單獨文件domain-person.properties
。
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
* @Author niujinpeng
* @Date 2018/12/6 22:54
*/
@Data
@Component
@Validated
@PropertySource(value = "classpath:domain-person.properties")
@ConfigurationProperties(value = "person")
public class PersonSource {
private String lastName;
private Integer age;
private Date birth;
private Map<String, String> maps;
private List<String> lists;
private Dog dog;
/**
* 支持數據校驗
*/
@Email
private String email;
}
5. 多環境配置
在主配置文件編寫的時候,文件名可以是 application-{name}.properties
.默認使用的是application.properties
.
5.1 properties 多環境
那么如何在配置文件中激活其他的配置文件呢?只需要在 application.properties
啟用其他文件。
# 激活 application-prod.properties文件
spring.profiles.active=prod
5.2 YAML 多環境
如果是使用 YAML 配置文件,我們可以使用文件塊的形式,在一個 YAML 文件就可以達到多文件配置的效果,下面是 Spring Boot 使用 YAML 文件進行多環境配置的方式。
server:
port: 8083
profiles:
active: dev # 指定環境為dev
# 使用三個---進行文檔塊區分
---
server:
port: 8084
spring:
profiles: dev
---
server:
port: 8085
spring:
profiles: prod
5.3 多環境激活方式
除了以上的兩種配置文件激活方式之外,還有另外兩種種激活方式。
- 命令行 ,運行時添加
--spring.profiles.active=prod
- Jvm 參數 ,運行時添加
-Dspring.profiles.active=prod
如果需要激活其他的配置文件,可以使用 spring.config.location=G:/application.properties
進行配置。
6. 配置文件加載順序
配置文件默認會從四個地方加載,且優先級從高到低。優先級高的配置會覆蓋優先級低的配置。如果多個位置的配置同時存在,不同的配置信息會形成互補配置。
-file: ./config/
-file: ./
-classpath: /config/
-classpath: /
7. 外部配置文件
Spring Boot 的外部配置文件加載的方式有很多,具體可以參考官方文檔。這寫配置加載優先級從高到底,優先級高的配置會覆蓋優先級低的配置。
下面介紹幾種常見的加載配置的順序。
- 命令行參數運行,所有的配置都可以在命令行上執行,多個配置空格隔開。
java -jar springboot-0.0.1-SNAPSHOT.jar --server.port=9999 --sercer.context-path=/spring
- jar 包目錄下的 application-{profile}.properties (或yml)文件
- jar 包里的 application-{profile}.properties (或yml)文件
- jar 包目錄下的 application.properties (或yml)文件
- jar 包里下的 application.properties (或yml)文件
文章代碼已經上傳到 GitHub Spring Boot 配置文件。
<完>
本文原發於個人博客:https://www.codingme.net 轉載請注明出處