1. 程式人生 > >SpringBoot學習筆記-SpringBoot配置

SpringBoot學習筆記-SpringBoot配置

SpringBoot學習筆記-SpringBoot配置

Table of Contents

1 Spring Boot配置

1.1 配置檔案

  • SpringBoot使用一個全域性的配置檔案
    • application.properties
    • application.yml: YAML(YAML Ain't Markup Language), 以資料為中心, 比json, xml更適合做配置檔案.
server:
  port: 8081
  • 配置檔案的作用: 修改SpringBoot自動配置的預設值.

1.2 YAML語法

  • 使用縮排表示層級關係.
  • 縮排時不允許使用Tab鍵,只允許使用空格.
  • 縮排空格數目不重要,只要相同層級的元素左側對齊即可
  • 大小寫敏感

1.3 YAML的資料結構

  • 物件: 鍵值對的集合.
  • 陣列: 一組按次序排列的值.
  • 字面量: 單個的,不可再分的值.

1.3.1 字面量

  • 字面量的字串預設不用加上單引號或者雙引號.
  • "" 雙引號, 不會轉移字串裡面的特殊字元.
    • "zhangsan\nlisi" -> zhangsan換行lisi
  • '' 單引號, 會轉義特殊字元, 特殊字元最終只是一個普通的字串資料.
    • "zhangsan\nlisi" -> zhangsan\nlisi
K:
  V: 字面量

1.3.2 物件

  • 物件的語法是物件加屬性的kv形式.
friends:
  lastName: zhangsan
  age: 20
  • 行內寫法
friends: {lastName: zhangsan, age: 18}

1.3.3 陣列(List,Set)

  • -值 來表示陣列的一個元素.
pets:
  - cat
  - dog
  - pig
  • 行內寫法
pets: [cat,dog,pig]

1.4 獲取yaml配置檔案值注入

  • yaml配置檔案
person:
 lastName: zhangsan
 age: 18
 boss: false
 birth: 2017/12/12
 maps: {k1: v1, k2: 12}
 lists:
   - lisi
   - zhaoliu
 dog:
   name: 小狗
   age: 2 
  • 元件bean
package com.devinkin.springboot.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 將配置檔案中的每一個屬性的值,對映到這個元件中
 * @ConfigurationProperties 告訴SpringBoot將本類中的所有屬性和配置檔案中相關的配置進行繫結
 *  prefix="person", 配置檔案中哪個下面的所有屬性進行一一對映
 *
 * @Component 只有這個元件是容器中的元件,才能使用容器提供@ConfigurationProperties的功能.
 */
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date birth;

    private Map<String, Object> maps;
    private List<Object> lists;

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getBoss() {
        return boss;
    }

    public void setBoss(Boolean boss) {
        this.boss = boss;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    @Override
    public String toString() {
        return "Person{" +
                "lastName='" + lastName + '\'' +
                ", age=" + age +
                ", boss=" + boss +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                '}';
    }
}
  • 匯入配置檔案處理器,以後編寫配置就有提示了
<!-- 匯入配置檔案處理器, 配置檔案進行繫結就會有提示 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
  • 如果從properties配置檔案中獲取值注入,idea需要注意一下設定.
    • 因為properties預設編碼是ascii,而idea預設編碼是utf-8

configuration2.png

1.5 @Value獲取值和@ConfigurationProperties獲取值的比較

  • 配置檔案無論是yaml還是properties都能獲取到值.
  • 如果說我們只是在某個業務邏輯中需要獲取一項配置檔案的某項值,我們就使用 @Value
  • 如果我們專門編寫了一個javaBean來和配置檔案進行校驗,我們就直接使用 @ConfigurationProperties
  @ConfigurationProperties @Value
功能 批量注入配置檔案的屬性 一個個指定
鬆散繫結(鬆散語法) 支援 不支援
SpEL 不支援 支援
JSR303資料校驗 支援 不支援
複雜型別封裝 支援 不支援

1.6 配置檔案注入值資料校驗

  • 使用 @Validated 註解.
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
    /**
     * <bean class="Person">
     *     <property name="lastName" value="字面量"/${key}從環境變數,配置檔案中獲取值/#{SpEL}></property>
     * </bean>
     */
//    @Value("${person.last-name}")
    // LastName必須是有效的格式
    @Email
    private String lastName;
}

1.7 @PropertySource和@ImportResource

  • @PropertySource 載入指定的配置檔案
  • 例: @PropertySource(value = {"classpath:person.properties"})
  • @ImportResource 匯入Spring的配置檔案, 讓配置檔案裡面的內容生效.
    • SpringBoot裡面沒有Spring的配置檔案,我們自己編寫的配置檔案,也不能自動識別.
    • 想讓Spring的配置檔案載入進來, 把 @ImportResource 標註在主配置類上.
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class SpringBoot02ConfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBoot02ConfigApplication.class, args);
    }
}
  • SpringBoot推薦給容器中新增元件的方式: 使用全註解的方式.
    • 使用 @Bean 給容器中新增元件
package com.devinkin.springboot.config;

import com.devinkin.springboot.service.HelloService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Configuration 它指明當前類是一個配置類,就是來替代之前的Spring配置檔案
 */
@Configuration
public class MyAppConfig {

    /**
     * 將方法的返回值新增到容器中: 容器中這個元件預設的id就是方法名
     * @return
     */
    @Bean
    public HelloService helloService() {
        System.out.println("配置類@Bean給容器中新增元件了...");
        return new HelloService();
    }
}

1.8 配置檔案的佔位符

  • RandomValuePropertySource: 配置檔案中可以使用隨機數
    • ${random.value}
    • ${random.int}
    • ${random.long}
    • ${random.int(10)}
    • ${random.int(1024,65536)}
  • 屬性配置佔位符
    • 可以在配置檔案中引入前面配置過的屬性(優先順序前面配置過的這裡都能用).
    • $app.name:預設值$ 來指定找不到屬性時的預設值.
# idea使用的是utf-8
# 配置person的值
person.last-name=張三${random.uuid}
person.age=${random.int}
person.birth=2019/02/01
person.boss=false
person.maps.k1=v1
person.maps.k2=v2
person.lists=a,b,c
person.dog.name=${person.last-name}_habi
person.dog.age=15

1.9 Profile

  • Profile是Spring對不同環境提供不同配置功能的支援,可以通過啟用,指定引數等方式快速切換環境.
  • 多profile檔案形式
    • 格式: application-{profile}.properties/yaml
  • yaml多profile文件模式, profiles 用於區分不同的文件.
    • 使用 --- 分割多文件塊.
server:
  port: 8081
spring:
  profiles:
    active: dev
---
server:
  port: 8082
spring:
  profiles: prod
---
server:
  port: 8083
spring:
  profiles: dev
---
  • 啟用profile的方式
    • 命令列: --spring.profiles.active=dev
    • 配置檔案: spring.profiles.active=dev
    • jvm引數: -Dspring.profiles.active=dev

1.10 配置檔案的載入位置

  • SpringBoot啟動會掃描一下位置下的 application.properties 或者 application.yml 檔案作為SpringBoot的預設配置檔案.
    • 優先順序從高到低的順序,所有位置的檔案都會被載入,高優先順序配置內容會覆蓋低優先順序配置內容.
    • ./config/
    • ./
    • classpath:/config/
    • classpath:/
    • SpringBoot會從這四個位置載入主配置檔案: 互補配置.
      • SpringBoot2.x棄用了 server.context-path , 改用 server.servlet.context-path
  • 可以配置 spring.config.location 來改變預設配置. 不過在專案除錯的時候不會使用該配置.
    • 專案打包以後,我們可以使用命令列引數的形式,在專案啟動的時候來指定配置檔案的新位置.
    • 指定的配置檔案和預設載入的這些配置檔案共同起作用, 互補配置.

1.11 外部配置載入順序

  • SpringBoot也可以從以下位置載入配置,優先順序從高到低,高優先順序的配置覆蓋低優先順序的配置,所有的配置會形成互補的配置.
    • 命令列引數.
    • 來自 java:comp/envJNDI 屬性.
    • Java系統屬性 System.getProperties()
    • 作業系統環境變數.
    • RandomValuePropertySource配置的 random.* 屬性值.
    • jar包外部的 application-{profile}.propertiesapplication.yml (帶spring.profile) 配置檔案
    • jar包內部的 application-{profile}.propertiesapplication.yml (帶spring.profile) 配置檔案
    • jar包外部的 application-{profile}.propertiesapplication.yml (不帶spring.profile) 配置檔案
    • jar包內部的 application-{profile}.propertiesapplication.yml (不帶spring.profile) 配置檔案
    • @Configuration 註解類上的 @PropertySource
    • 通過 SpringApplication.setDefaultProperties 指定的預設屬性.

1.12 自動配置原理

  • SpringBoot啟動的時候載入主配置類,開啟了自動配置功能 @EnableAutoConfiguration
  • @EnableAutoConfiguration 作用: 將類路徑下的 META-INF/spring.factories 裡面配置的所有 EnableAutoConfiguration 的值加到了容器中.
    • 利用 EnableAutoConfigurationImportSelector 給容器匯入一些元件.
    • 檢視 EnableAutoConfigurationImportSelector 其父類的 selectImports 方法.
    • List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes); 獲取候選的配置.
    • SpringFactoriesLoader.loadFactoryNames() 掃描所有jar包類路徑下的 META-INF/spring.factories
    • 把掃描到的這些檔案的內容包裝成 Properties 物件
    • Properties 中獲取到 EnableAutoConfiguration.class 類(類名)對應的值,然後把它們新增到容器中.
  • 每一個自動配置類進行自動配置功能.
  • HttpEncodingAutoConfiguration 為例解釋自動配置原理.
    • 根據當前不同的條件判斷,決定這個配置類是否生效.
@Configuration
// 啟動指定類的ConfigurationProperties功能
// 將配置檔案中對應的值和HttpEncodingProperties繫結起來.並把 HttpEncodingProperties 加入到IOC容器中.
@EnableConfigurationProperties(HttpEncodingProperties.class)
// Spring底層@Conditional註解,根據不同得到條件,如果滿足指定的條件,整個配置類裡面的配置就會生效.
// 判斷當前應用是否為Web應用
@ConditionalOnWebApplication
// 判斷當前專案有沒有CharacterFilter類(SpringMVC進行亂碼解決的過濾器)
@ConditionalOnClass(CharacterEncodingFilter.class)
// 判斷配置檔案中是否存在某個配置 spring.http.encoding.enabled, 如果不存在, 判斷也是成立的.
// 即使配置檔案中不配置 spring.http.encoding.enabled, 也是預設生效的.
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {}
  • 所有在配置檔案中配置的屬性都是在 xxxProperties 類中封裝著, 配置檔案能配置什麼就可以參照某個功能對應的這個屬性類.
// 從配置檔案中獲取指定的值和bean的屬性進行繫結.
  @ConfigurationProperties(prefix = "spring.http.encoding")
  public class HttpEncodingProperties {}
  • 給容器中新增一個元件, 這個元件的某些值需要從properties中獲取.
@Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
public CharacterEncodingFilter characterEncodingFilter() {
    CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
    filter.setEncoding(this.properties.getCharset().name());
    filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
    filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
    return filter;
}

1.13 SpringBoot精髓

  • SpringBoot啟動會載入大量的自動配置類
  • 看SpringBoot預設寫好的自動配置類有沒有我們需要的功能.
  • 我們再來看自動配置類中到底配置了哪些元件.(只要我們使用的元件有,我們就不需要再來配置).
  • 給容器中自動配置類新增元件的時候,會從 Properties 類中獲取某些屬性, 我們就可以在配置檔案中指定這些屬性的值.

1.14 @Condition派生註解

  • @Condition 作用: 指定的條件成立, 才給容器中新增元件, 配置類裡面的所有內容才生效.
  • Condition註解的擴充套件
@Condition擴充套件註解 作用(判斷是否滿足當前指定條件)
@ConditionOnJava 系統的Java版本是否符合要求
@ConditionOnBean 容器中存在指定Bean
@ConditionOnMissingBean 容器中不存在指定Bean
@ConditionOnExpression 滿足SpEL表示式指定
@ConditionOnClass 系統中有指定的類
@ConditionOnMissingClass 系統中沒有指定的類
@ConditionOnSingleCandidate 容器中只有一個指定的Bean,或者這個Bean是首選Bean
@ConditionOnProperty 系統中指定的屬性是否有指定的值
@ConditionOnResource 類路徑下是否存在指定資原始檔
@ConditionOnWebApplication 類路徑下是否存在指定資原始檔
  • 在配置檔案中新增如下配置 debug=true 啟用debug模式, 可以檢視載入了哪些自動配置類.

Date: 2018-11-20 20:15

Author: devinkin

Created: 2018-11-24 六 19:48

Validate