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

文章已經收錄在 Github.com/niumoo/JavaNotes ,更有 Java 程序員所須要掌握的核心知識,歡迎Star和指教。
歡迎關注個人 公衆號,文章每週更新。
注意:本 Spring Boot 系列文章基於 Spring Boot 版本 v2.1.1.RELEASE 進行學習分析,版本不一樣可能會有細微差異。

前言

不論是經過官方提供的方式獲取 Spring Boot 項目,仍是經過 IDEA 快速的建立 Spring Boot 項目,咱們都會發如今 resource 有一個配置文件 application.properties,也有多是application.yml.這個文件也就是 Spring Boot 的配置文件。html

<!-- more -->java

1. YAML 文件

Spring Boot 中,官方推薦使用 properties 或者 YAML 文件來完成配置,對於 YAML 文件格式還不瞭解的能夠查看官方的具體格式,這裏只作簡單介紹。 git

YAML 語法規則:程序員

  • 大小寫敏感
  • 縮進表示層級
  • 縮進只能使用空格
  • 空格的數量不重要,可是相同層級的元素要左側對齊
  • # 開頭的行表示註釋

YAML 支持的數據結構:github

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

name: Darcy
   age: 12
   # ~表示NULL值
   email: ~ 
   # 多行字符串可使用|保留換行符,也可使用>摺疊換行。
   # +表示保留文字塊末尾的換行,-表示刪除字符串末尾的換行。
   message:|-
     Hello world

2.數組,一組按次序排列的值。web

lang:
    - java
    - golang
    - c
    或者行內寫法
   lang:[java,golang,c]

3.對象,鍵值對的集合。面試

person:
     name:Darcy
     age:20
    或者行內寫法
   person:{name:Darcy,age:20}

使用 YAML 支持的三種數據結構經過組合能夠造成複雜的複合結構。spring

# 服務啓動端口號
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 加載shell

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
  2. jar 包目錄下的 application-{profile}.properties (或yml)文件
  3. jar 包裏的 application-{profile}.properties (或yml)文件
  4. jar 包目錄下的 application.properties (或yml)文件
  5. jar 包裏下的 application.properties (或yml)文件

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

最後的話

文章每週持續更新,本文 Github.com/niumoo/JavaNotes 已收錄。更有一線大廠面試點,Java程序員所須要掌握的核心知識等文章,也整理了不少個人文字,歡迎 Star 和完善,但願咱們一塊兒變得優秀。

文章有幫助能夠點「」在看或 Star,我都喜歡,謝謝你!
要實時關注我更新的文章以及分享的乾貨,能夠關注「 未讀代碼 」公衆號,公衆號回覆 666 能夠領取不少資料

公衆號

相關文章
相關標籤/搜索