前言
本章主要講解 Spring Boot 中的配置文件。
配置文件
SpringBoot使用一個全局的配置文件,配置文件名是固定的;放置在src/main/resources 目錄或者類路徑的 /config 下。Spring Boot提供了兩種常用的配置文件,分別是properties文件和yml文件。他們的作用都是修改Spring Boot自動配置的默認值。
-
application.properties
-
application.yml
Spring Boot 不僅支持常規的 properties 配置文件,還支持 yaml 語言的配置文件。yaml 是以數據爲中心的語言,在配置數據的時候具有面向對象的特徵。
Yaml
1、Yaml 簡介
yml是YAML(YAML Ain’t Markup Language)語言的文件,以數據爲中心,比json、xml等更適合做配置文件。
yml和xml相比,少了一些結構化的代碼,使數據更直接,一目瞭然。
yml和json呢?沒有誰好誰壞,合適纔是最好的。yml的語法比json優雅,註釋更標準,適合做配置文件。json作爲一種機器交換格式比yml強,更適合做api調用的數據交換。
- Yaml
server: port: 8081
- XML:
<server> <port>8081</port> </server>
2、Yaml語法
以空格的縮進程度來控制層級關係。空格的個數並不重要,只要左邊空格對齊則視爲同一個層級。注意不能用tab代替空格。且大小寫敏感。支持字面值,對象,數組三種數據結構,也支持複合結構。
k:
(空格)v:表示一對鍵值對(空格必須有);
以 空格 的縮進來控制層級關係;只要是左對齊的一列數據,都是同一個層級的
server:
port: 8081
path: /hello
基本格式要求
- YAML大小寫敏感;
- 使用縮進代表層級關係;
- 縮進只能使用空格,不能使用TAB,不要求空格個數,只需要相同層級左對齊(一般2個或4個空格)
- 註釋和properties相同,使用
#
作爲註釋,YAML中只有行註釋。
值的寫法
-
字面值:字符串,布爾類型,數值,日期。字符串默認不加引號,單引號會轉義特殊字符,雙引號不會。日期格式支持yyyy/MM/dd HH:mm:ss
-
對象:由鍵值對組成,形如 key:(空格)value 的數據組成。冒號後面的空格是必須要有的,每組鍵值對佔用一行,且縮進的程度要一致,也可以使用行內寫法:{k1: v1, …kn: vn}
-
數組:由形如 -(空格)value 的數據組成。短橫線後面的空格是必須要有的,每組數據佔用一行,且縮進的程度要一致,也可以使用行內寫法: [1,2,…n]
-
複合結構:上面三種數據結構任意組合
3、Yaml運用
對象、Map(屬性和值)(鍵值對):
k: v:在下一行來寫對象的屬性和值的關係;注意縮進
對象還是k: v的方式
friends:
lastName: zhangsan
age: 20
行內寫法:
friends: {lastName: zhangsan,age: 18}
數組(List、Set):
- 用
-
值表示數組中的一個元素
pets:
- cat
- dog
- pig
行內寫法
pets: [cat,dog,pig]
配置文件值注入
person:
# 屬性賦值
lastName: helloword
age: 12
boss: true
birth: 2019/08/28
# map賦值
maps: {k1: v1,k2: 12}
# list賦值
lists:
- lisi
- zhaoliu
# 對象賦值
dog:
name: xiaogou
age: 12
創建實體類Person .java 獲取配置文件中的屬性值,通過註解@ConfigurationProperties獲取配置文件中的指定值並注入到實體類中。
/**
* 將配置文件中配置的每一個屬性的值,映射到這個組件中
* @ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關的配置進行綁定;
* prefix = "person":配置文件中哪個下面的所有屬性進行一一映射
*
* 只有這個組件是容器中的組件,才能容器提供的@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;
private Dog dog;
我們可以導入配置文件處理器,以後編寫配置就有提示了
<!--導入配置文件處理器,配置文件進行綁定就會有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Test 測試類:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
Person person;
@Test
public void contextLoads() {
System.out.println(person.toString());
}
}
結果:
Person{lastName='helloword', age=12, boss=true, birth=Wed Aug 28 00:00:00 CST 2019, maps={k1=v1, k2=12}, lists=[lisi, zhaoliu], dog=com.example.demo.pojo.Dog@54562ea6}
4、Properties
properties文件大家經常用,這裏就簡單介紹一下。其語法結構形如:key=value。注意中文亂碼問題,需要轉碼成ASCII。
#屬性賦值
person.lastName = helloword
person.age= 12
person.boss= true
person.birth= 2019/08/28
# map賦值
person.maps.k1=v1
person.maps.k2=v2
# list賦值
person.lists=lisi,zhangsan
# 對象賦值
person.dog.name=xiaogou
person.dog.age=12
從配置文件中取值注入到實體類中,和YAML是一樣的。
/**
* 將配置文件中配置的每一個屬性的值,映射到這個組件中
* @ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關的配置進行綁定;
* prefix = "person":配置文件中哪個下面的所有屬性進行一一映射
*
* 只有這個組件是容器中的組件,才能容器提供的@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;
private Dog dog;
配置文件注入值數據校驗
@Component
@ConfigurationProperties(prefix = "person")
@Validated //注入值數據校驗的註解
public class Person {
//lastName必須是郵箱格式
@Email
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
5、配置文件的存取
Spring Boot通過ConfigurationProperties註解從配置文件中獲取屬性。從上面的例子可以看出ConfigurationProperties註解可以通過設置prefix指定需要批量導入的數據。支持獲取字面值,集合,Map,對象等複雜數據。ConfigurationProperties註解還有其他特麼呢?它和Spring的Value註解又有什麼區別呢?
@ConfigurationProperties和@Value優缺點
-
可以從配置文件中批量注入屬性;
-
支持獲取複雜的數據類型;
-
對屬性名匹配的要求較低,比如user-name,user_name,userName,USER_NAME都可以取值;
-
支持JAVA的JSR303數據校驗;
-
缺點是不支持強大的SpEL表達式;
Value註解的優缺點正好相反,它只能一個個配置注入值;不支持數組、集合等複雜的數據類型;不支持數據校驗;對屬性名匹配有嚴格的要求。最大的特點是支持SpEL表達式,使其擁有更豐富的功能。
@Value獲取值和@ConfigurationProperties獲取值比較
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的屬性 | 一個個指定 |
鬆散綁定(鬆散語法) | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303數據校驗 | 支持 | 不支持 |
複雜類型封裝 | 支持 | 不支持 |
-
配置文件yml還是properties他們都能獲取到值;
-
如果說,我們只是在某個業務邏輯中需要獲取一下配置文件中的某項值,使用@Value;
-
如果說,我們專門編寫了一個javaBean來和配置文件進行映射,我們就直接使用@ConfigurationProperties;
6、@PropertySource
&@ImportResource
&@Bean
概述:
我們對於一些屬性的配置肯定不會寫在一個配置文件中這樣顯得耦合性太強,如何去指定配置文件呢? 下面我們就通過@PropertySource、@ImportResource、@Bean的使用這幾個屬性的學習來解決此問題。
@PropertySource:加載指定的配置文件;
/**
* 將配置文件中配置的每一個屬性的值,映射到這個組件中
* @ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關的配置進行綁定;
* prefix = "person":配置文件中哪個下面的所有屬性進行一一映射
*
* 只有這個組件是容器中的組件,才能容器提供的@ConfigurationProperties功能;
* @ConfigurationProperties(prefix = "person")默認從全局配置文件中獲取值;
*
*/
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
//@Validated
public class Person {
//lastName必須是郵箱格式
// @Email
//@Value("${person.last-name}")
private String lastName;
//@Value("#{11*2}")
private Integer age;
//@Value("true")
private Boolean boss;
@ImportResource:導入Spring的配置文件,讓配置文件裏面的內容生效;
Spring Boot裏面沒有Spring的配置文件,我們自己編寫的配置文件,不能自動識別;
想讓Spring的配置文件生效,加載進來;@ImportResource標註在一個配置類上
@ImportResource標註在一個配置類上但是這種方式官方並不推薦
@ImportResource(locations = {"classpath:beans.xml"})
不來編寫Spring的xml配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloService" class="com.atguigu.springboot.service.HelloService"></bean>
</beans>
SpringBoot推薦給容器中添加組件的方式;推薦使用全註解的方式
1、配置類 @Configuration --------- Spring配置文件
2、使用 @Bean給容器中添加組件
/**
* @Configuration:指明當前類是一個配置類;就是來替代之前的Spring配置文件
*
* 在配置文件中用<bean><bean/>標籤添加組件
*
*/
@Configuration
public class MyAppConfig {
//將方法的返回值添加到容器中;容器中這個組件默認的id就是方法名
@Bean
public HelloService helloService02(){
System.out.println("配置類@Bean給容器中添加組件了...");
return new HelloService();
}
}
配置文件佔位符
1、隨機數
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int[1024,65536]}
2、佔位符獲取之前配置的值,如果沒有可以是用:指定默認值
person.last-name=張三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
Profile
Profile是Spring對不同 環境提供不同配置功能的支持,可以通過激活,指定參數等形式快速切換環境。
1、多Profile文件(properties文件)
編寫的時候,文件名可以是: application-{profile}.properties/yml
默認使用application.properties的配置;
-
創建配置文件application-dev.properties,此文件爲開發環境的配置文件
server.port=8081
-
創建配置文件allpication-prod.properties,此文件爲生產環境的配置文件
server.port=8082
-
在appliapplication.properties中添加使用的環境
#默認配置文件的端口 server.port=8080 #使用的環境名稱 spring.profiles.active=dev
2、yml支持多文檔塊方式
在以下yml文件中,用 ---
分爲三個ducement,第一個ducument爲默認的配置文件,第二個部分爲dev的配置文件,第三個部分爲prod的配置文件。在默認doucment中使用spring.profiles.active設置使用哪個ducument 的配置。
server:
port: 8081
spring:
profiles:
active: prod #指定運行哪個環境
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8084
spring:
profiles: prod
3、激活指定profile
-
在配置文件中指定
spring.profiles.active=dev
-
Program arguments
在Program arguments中配置參數--spring.profiles.active=dev
-
命令行:
將項目打包成jar包,切換到命令行的界面下使用命令 : java -jarspring-boot-02-config-0.0.1-SNAPSHOT.jar
--spring.profiles.active=dev;
可以直接在測試的時候,配置傳入命令行參數
- 虛擬機參數;
-Dspring.profiles.active=dev
配置文件加載位置
Spring Boot 啓動會掃描以下位置的application.properties或者application.yml文件作爲Spring boot的默認配置文件
-
file:
../config/
-
file:
../
-
classpath:
/config/
-
classpath:
/
即根目錄下的config目錄下,然後是 根目錄下,然後是classpath路徑下的config目錄下,最後是classpath路徑下。
優先級由高到底,高優先級的配置會覆蓋低優先級的配置;如果SpringBoot中四個位置都有配置文件,會從這四個位置全部加載主配置文件;並且形成互補配置;
我們還可以通過spring.config.location
來改變默認的配置文件位置
-
項目打包好以後,我們可以使用命令行參數的形式,啓動項目的時候來指定配置文件的新位置;指定配置文件和默認加載的這些配置文件共同起作用形成互補配置;
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties
外部配置加載順序
SpringBoot也可以從以下位置加載配置; 優先級從高到低;高優先級的配置覆蓋低優先級的配置,所有的配置會形成互補配置
-
命令行參數
所有的配置都可以在命令行上進行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
多個配置用空格分開; --配置項=值
-
來自java:comp/env的JNDI屬性
-
Java系統屬性(System.getProperties())
-
操作系統環境變量
-
RandomValuePropertySource配置的random.*屬性值
由jar包外 向jar包內 進行尋找;優先加載帶profile
-
jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
-
jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
再來加載不帶profile
-
jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
-
jar包內部的application.properties或application.yml(不帶spring.profile)配置文件
-
@Configuration註解類上的@PropertySource
-
通過SpringApplication.setDefaultProperties指定的默認屬性
總結
Spring Boot 配置文件就講到這裏,還有一個自動配置原理,下一篇講解。