1. 程式人生 > >【玩轉SpringBoot】配置檔案yml的正確開啟姿勢

【玩轉SpringBoot】配置檔案yml的正確開啟姿勢


序言


在很久以前,Spring的配置檔案是基於XML的。它的名字就是applicationContext.xml,沒錯,就只有這一個xml檔案。

它裡面配置了所有的東西。但是資料庫資訊通常會單獨拿出來,放入一個properties檔案,通常叫db.properties。

後來覺著一個xml裡的東西實在太多了,就按功能拆分成幾個獨立的xml。

spring-dao.xml是dao層,spring-service.xml是service層,spring-tx.xml是事務相關,dispatcher-servlet.xml是web相關。

這麼多的xml怎麼辦呢?很簡單,就是在applicationContext.xml裡都引用它們即可。


隨著JDK在1.5加入了對註解的支援,Spring也慢慢的向註解轉化。直至後來一個xml都不剩,全部變為註解,連web.xml都沒有了。

是xml不行了,還是註解太牛X了,其實它們是等價的,連官網上都說它們一摸一樣,故而不做推薦,讓使用者根據實際情況自己選擇。

不過,最終歷史還是拋棄了XML,肯定是多方面的原因,可能如下:

1)人們厭倦了XML,出現審美疲勞

2)試用了註解很爽,一發不可收拾

3)註解代表著先進的生產力,極大提升了效率

4)XML拖沓累贅,註解清爽乾脆

5)大家都覺得使用註解比使用XML更牛B。

於是乎,一個輝煌的新時代碾壓了一個曾經輝煌的曾經的新時代。

呵呵,歷史是什麼,就是個車輪。一切皆可碾壓。

總之,既有實際實踐問題,又有思想意識問題,說不清,道不明。

隨著SpringBoot的橫空出世,配置檔案的概念又發了變化。

SpringBoot強調自動配置(也叫自動裝配),所以配置對它來說很重要。

配置檔案屬於配置的一部分,自然也變得非常重要,於是yml就應勢站了起來。

yml從未像現在這樣流行,成了新時代的網紅。


yml配置檔案的格式


每種新事物的流行,總會有它比舊事物更好的地方。

作為Java界配置檔案鼻祖,非properties檔案莫屬,它裡面的格式就不用再舉例了吧。

它是一維非結構化的,一行一個,寫多了容易亂。

而yml檔案是二維結構化的,有嚴格的縮排,結果就是層次分明,非常清晰。

而且,常用的配置都能得到支援,這就是它的優勢,所以就流行起來了。

一、List配置格式,如下圖01:

 

二、Map配置格式,如下圖02:

 

三、List套List格式,如下圖03:

 

四、List套Map格式,如下圖04:

 

五、Map套Map格式,如下圖05:

 

六、Map套List格式,如下圖06:

 

雖然有些巢狀可能並不適用,這裡只是說明yml支援這樣的巢狀,如果願意的話,巢狀層次還可以更深。


yml配置檔案內容的儲存


大家都知道SpringBoot是由Spring發展而來的,Spring裡是有Environment這個概念的。

所有的環境變數、系統屬性、配置檔案內容都會放進去。

通常的配置項都是一些key=value,就和properties檔案是一樣的。所以Environment底層也是這樣實現的。

但到了SpringBoot中,配置檔案變為yml了,是二維結構化的,根本沒有辦法直接用key=value這種形式表示。

但是,yml配置檔案的內容還必須要放入到Environment中去。那怎麼辦呢?看來二者必須要修改其一了。

由於Spring已經很多年了,它裡面的很多概念都已經固化下來了,包括Environment內部的結構與實現。

因此,最終選擇yml去適配Environment,把二維結構化變為一維非結構化,即把有層次的變為簡單的key=value形式。

這在程式設計裡有一個專門的術語,叫扁平化。其實人員管理裡面也有扁平化。

具體規則也非常簡單,把父子關係用點號(.)表示,把列表索引用中括號([])表示。

把剛剛的配置內容輸出來看看,如下圖070809:


這樣就完成了扁平化,就可以存入到Environment中去了。

等號(=)前面的就是key,後面的就是值。


直接粗暴的使用yml配置檔案內容


由於yml配置檔案內容最終會進入Environment中,所以就等於直接粗暴的從Environment中讀取值。

此時,key必須要寫成上面那樣子,否則取不到值。

一、直接從Environment中讀取,如下圖10:

 

結果輸出如下圖11:

 

二、使用@Value註解,如下圖12:

 

結果輸出如下圖13:

 

這就是簡單粗暴的方式,除了看上去不美觀之外,還把yml的結構化特徵給丟失了。

其實,還有一個比較嚴重的問題,就是隻能獲取到最終key對應的單個值,如果想獲取一個List或Map作為返回值,是不行的。


優雅的使用yml配置檔案內容


key=value這種形式其實就是個Map,而Map其實和Java Bean差的並不多,只不過Bean中是屬性名和屬性值罷了。

Map套Map就等於Bean套Bean,這樣無論結構形式還是語義表達都能很完美的對映過來。

且Bean是強型別的,屬性名和屬性型別一目瞭然,比Map強多了。

所以yml配置檔案裡的內容可以對映為Java裡的Bean,這就是SpringBoot推薦的優雅的使用方式。

這裡的核心問題就是,yml裡的配置項要和Bean中的屬性名稱和型別對應好,不然會出問題。

下面請看一個示例,自己瞎編了一個游泳比賽的得分和獎品的配置。

含有一等獎、二等獎、三等獎的得分割槽間,和它們分別對應的獎品名稱和數量。

如下圖14:

 

可以看到scores對應的是一個列表,它有三個元素,每個元素都有level、lowBound、highBound三個屬性。

awards對應一個Map,它有三個key,分別是level1、level2、level3,每個key對應的值又是一個列表。

且列表都含有兩個元素,且每個元素都有name、count兩個屬性。

如果這個明白了,下面請看它對應的Bean,如下圖15:

 

Score和Award是兩個靜態內部類。一個有三個屬性,一個有兩個屬性。

ScoreProperties類中有兩個屬性,一個是scores,型別是List<Score>。

一個是awards,型別是Map<String, List<Award>>。

可以看出,它們和yml的結構是完全吻合的。沒有難度吧。

為了使它用起來更優雅,SpringBoot定義了兩個註解來助它一臂之力。

首先,在Bean上標上@ConfigurationProperties,表示它是一個“配置屬性”。

如下圖16:

 

其次,在另一個類上使用@EnableConfigurationProperties註解將其引入。

如下圖17:

 

經過這兩步,這個“配置屬性”類就已經被註冊到容器裡了,就變成一個普通的bean了。

這樣就可以把它注入到需要的地方,如下圖18:

 

使用的是構造方法注入,並輸出一下它的值,看看和yml中配置的是否一樣。

結果如下圖19:

 

可以看到,完全沒有問題。這就是SpringBoot推薦的方式。

SpringBoot框架內部的原始碼都是這樣用的。

既然“