Y服務-你真的懂 Yaml 嗎?
在Java 的世界裡,配置的事情都交給了 Properties,要追溯起來這個模組還是從古老的JDK1。0 就開始了的。
“天哪,這可是20年前的東西了,我居然還在用 Properties。。”
然而,本文的主角並不是Properties,而是Yaml。這是新時代裡微服務架構上的寵兒,和 Properties 相比起來,Yaml 顯得有些弄潮兒。
以往的大多數專案裡,我們都可以發現 Properties配置檔案的蹤跡,這包括用作業務屬性配置的、機機接×××互的、國際化的等等用途。
而少量的一些情況下,也存在一些“混合式”的做法,比如:
使用 Xml 來表示一些模板
使用一個 Json 格式化的字串
裸奔的文字格式,應用自解析
。。。
混雜的配置方式往往出現在一些充滿“壞味道”的專案裡頭,因為程式碼陳舊、斯人已矣 等原因,很難形成統一的方式。
然而,除開 Properties 屬性檔案這種簡單的配置方式之外,採用其他的方法不外乎都是為了適應配置複雜、多元化的訴求。
那麼,Yaml 就是應對這種場景而產生的,在 SpringBoot 的官方文件中,有不少篇幅是 使用了 Yaml 語法的配置格式。
下面介紹一下 Yaml 以及它是如何使用的。
一、什麼是 Yaml
來自百科的定義
:
“Yaml 是一個可讀性高,易用的資料序列化格式,由 Clark Evans 在2001年首次發表。”
可見 Yaml 並不是一個很新的東西,只是在以前接觸的人不多罷了。此外,Yaml也被各種程式語言及框架所支援, 通用性很高。
在Java體系中,一般的微服務框架都支援甚至優先推薦使用 Yaml 作為首選的配置語言。
而 Yaml 本身具有什麼特點? 看看下面的一個例項:
environments: dev: url: https://dev。example。com name: Developer Setup prod: url: https://another。example。com name: My Cool App
這段語法等價的 Properties 為:
environments。dev。url=https://dev。example。comenvironments。dev。name=Developer Setupenvironments。prod。url=https://another。example。comenvironments。prod。name=My Cool App
可見, yaml 相對來說更加的結構化,更適合用來表達一個物件。
它在語法上有這樣的特點:
大小寫敏感
使用空格縮排表示層級關係,摒棄使用Tab鍵,這主要是考慮到不同平臺上文字展現時需要對齊
縮排的空格數目不重要,只要相同層級的元素左側對齊即可
使用 # 開頭作為註釋行
使用 連線符(-)開頭來描述陣列元素
對比 Properties
Properties 可以很好的實現 Key-Value 的配置,包括作為一些國際化內容的配置方式。
但 Properties 很難表現多層級的巢狀關係,此時如果用 Yaml 可以較好的彌補該短板。
對比 Json
Yaml 與 Json本身沒有太多的優劣之分,兩者都是結構化的表示式語言,但是Json的設計重點在於簡單易用、方便傳輸的特性;
而 Yaml 則側重於可讀性(更加在乎外觀),幾乎可以把 Yaml 看做是 Json 的一個“超集”,即可讀性更高(更漂亮) 的結構化格式。
此外,Json更加便於生成和解析,適合在各種跨語言、分散式的環境中傳輸和互動;與此同時, Yaml 則一般只是用作的配置較多。
關於
Yaml 的定義
可以訪問下面的地址:
http://www。yaml。org/spec/1。2/spec。html
二、Yaml 的語法
Yaml 是非常簡單的, 它所定義的元素只有三個:
物件:就是鍵值對的集合,對應於Java 中的 HashMap
陣列:指一組按序排列的值,對應於Java 中的 List
單值:單個的、不可再分的值,比如 3,“Jackson”
物件如何表示
一個物件的屬性、巢狀關係透過空格縮排對齊來表示,如下:
article: title: 一個人的自白書 author: name: 陳玲 gender: female
陣列如何表示
陣列的元素透過連線符(-)來表示,如下:
article: title: 一個人的自白書 tags: - 傳記 - 社會 - 人物
構成物件、陣列內容的基本單元是單值,Yaml支援的單個值的型別有七種,如下:
類型範例
字串Bob布林值true整數199浮點數19。91Null~時間2001-12-14T22:14:09。10+08:00日期2019-01-09
其中,日期、時間使用的是 ISO 8601 國際標準格式,關於它的定義可以參考:
https://www。w3。org/TR/NOTE-datetime
一般情況下單個值會在一行內結束。但如果遇到多行的字串,可以使用一些特殊字元表示,
比如:
text: | Hello World
對應的結果為:
{ text: ‘Hello\nWorld\n’ }
可以用
+
表示保留字串末尾的換行,
-
表示刪除字串末尾的換行:
text1: |+ Hellotext2: |- Hello
對應的結果為:
{ text1: ‘Hello\n\n\n’, text2: ‘Hello’ }
除此之外,Yaml 還可以支援引用、函式、正則表示式等高階用法,但專案上一般很少用到。
三、操作 Yaml
目前用來操作 Yaml 的常用元件是 Snake Yaml,這個庫支援標準的
Yaml 1.1 版本
。
SpringBoot 官方文件也介紹了整合該框架的方式,參考下面的地址:
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-loading-yaml
下面提供 將SnakeYaml 整合到專案的樣例。
A。 引入框架
在Maven的pom。xml檔案中新增:
B。 程式碼片段
實現載入配置檔案
如下面的程式碼,實現了從類路徑config。yml檔案中載入 yaml 配置內容:
InputStream inputStream = YamlUtil。class。getClassLoader() 。getResourceAsStream(“config。yml”);Yaml yaml = new Yaml();Map
實現物件轉換
定義如下的Pojo 物件:
public static class A{ private String name = “hello”; private List bs = new ArrayList(); public String getName() { return name; } public void setName(String name) { this。name = name; } public List getBs() { return bs; } public void setBs(List bs) { this。bs = bs; }}public static class B{ private String id = UUID。randomUUID()。toString(); public String getId() { return id; } public void setId(String id) { this。id = id; }}
透過 SnakeYaml 將物件輸出為 Yaml 格式的程式碼:
A a = new A();a。getBs()。add(new B());a。getBs()。add(new B());Yaml yaml = new Yaml();String aString = yaml。dumpAsMap(a);System。out。println(aString);
輸出結果如下:
bs:- id: b3688f05-ea7e-436b-bc9a-9c5df555c7fd- id: 7906224d-8ecc-43b8-bc3b-07985bc18ebdname: hello
此時如果希望將Yaml 文字反過來轉換為 A 物件,可以執行下面的程式碼:
A a1 = new Yaml()。parseToObject(aString, A。class);。。。
C。 完整案例
最終,我們可以將 Yaml 文件的操作封裝為一個工具類,方便在業務程式碼中整合。
YamlUtil.java
public class YamlUtil { /** * 從資原始檔載入內容,並解析為Map物件 * * @param path * @return */ public static Map
至此,我們已經完成了 Yaml 的讀寫。當然,除了上述的Snake Yaml 之外,還可以使用 流行的 Jackson 元件了進行解析,這裡不再過多贅述,有興趣的朋友可以自行嘗試。