Springboot 系列(二)Spring Boot 配置文件


注意:本 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 支持的數據結構:

  1. 單純的變量,不可再分的單個的值,如數字,字符串等。

    name: Darcy
    age: 12
    # ~表示NULL值
    email: ~ 
    # 多行字符串可以使用|保留換行符,也可以使用>折疊換行。
    # +表示保留文字塊末尾的換行,-表示刪除字符串末尾的換行。
    message:|-
      Hello world
    
  2. 數組,一組按次序排列的值。

    lang:
     - java
     - golang
     - c
    # 或者行內寫法
    lang:[java,golang,c]
    
  3. 對象,鍵值對的集合。

    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 的外部配置文件加載的方式有很多,具體可以參考官方文檔。這寫配置加載優先級從高到底,優先級高的配置會覆蓋優先級低的配置。

下面介紹幾種常見的加載配置的順序。

  1. 命令行參數運行,所有的配置都可以在命令行上執行,多個配置空格隔開。
java -jar springboot-0.0.1-SNAPSHOT.jar --server.port=9999 --sercer.context-path=/spring
  1. jar 包目錄下的 application-{profile}.properties (或yml)文件
  2. jar 包里的 application-{profile}.properties (或yml)文件
  3. jar 包目錄下的 application.properties (或yml)文件
  4. jar 包里下的 application.properties (或yml)文件

文章代碼已經上傳到 GitHub Spring Boot 配置文件

<完>
本文原發於個人博客:https://www.codingme.net 轉載請注明出處


免責聲明!

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



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