溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Yaml如何理解

發(fā)布時間:2022-01-07 21:47:22 來源:億速云 閱讀:134 作者:柒染 欄目:編程語言

Yaml如何理解,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

在Java 的世界里,配置的事情都交給了 Properties,要追溯起來這個模塊還是從古老的JDK1.0 就開始了的。

"天哪,這可是20年前的東西了,我居然還在用 Properties.."

然而,本文的主角并不是Properties,而是Yaml。這是新時代里微服務(wù)架構(gòu)上的寵兒,和 Properties 相比起來,Yaml 顯得有些弄潮兒。

以往的大多數(shù)項目里,我們都可以發(fā)現(xiàn) Properties配置文件的蹤跡,這包括用作業(yè)務(wù)屬性配置的、機機接×××互的、國際化的等等用途。
而少量的一些情況下,也存在一些"混合式"的做法,比如:

  • 使用 Xml 來表示一些模板

  • 使用一個 Json 格式化的字符串

  • 裸奔的文本格式,應(yīng)用自解析
    ...

混雜的配置方式往往出現(xiàn)在一些充滿"壞味道"的項目里頭,因為代碼陳舊、斯人已矣 等原因,很難形成統(tǒng)一的方式。
然而,除開 Properties 屬性文件這種簡單的配置方式之外,采用其他的方法不外乎都是為了適應(yīng)配置復(fù)雜、多元化的訴求。

那么,Yaml 就是應(yīng)對這種場景而產(chǎn)生的,在 SpringBoot 的官方文檔中,有不少篇幅是 使用了 Yaml 語法的配置格式。
下面介紹一下 Yaml 以及它是如何使用的。

一、什么是 Yaml

來自百科的定義
"Yaml 是一個可讀性高,易用的數(shù)據(jù)序列化格式,由 Clark Evans 在2001年首次發(fā)表。"
可見 Yaml 并不是一個很新的東西,只是在以前接觸的人不多罷了。此外,Yaml也被各種編程語言及框架所支持, 通用性很高。
在Java體系中,一般的微服務(wù)框架都支持甚至優(yōu)先推薦使用 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.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

可見, yaml 相對來說更加的結(jié)構(gòu)化,更適合用來表達(dá)一個對象。
它在語法上有這樣的特點:

  • 大小寫敏感

  • 使用空格縮進表示層級關(guān)系,摒棄使用Tab鍵,這主要是考慮到不同平臺上文本展現(xiàn)時需要對齊

  • 縮進的空格數(shù)目不重要,只要相同層級的元素左側(cè)對齊即可

  • 使用 # 開頭作為注釋行

  • 使用 連接符(-)開頭來描述數(shù)組元素

對比 Properties
Properties 可以很好的實現(xiàn) Key-Value 的配置,包括作為一些國際化內(nèi)容的配置方式。
但 Properties 很難表現(xiàn)多層級的嵌套關(guān)系,此時如果用 Yaml 可以較好的彌補該短板。

對比 Json
Yaml 與 Json本身沒有太多的優(yōu)劣之分,兩者都是結(jié)構(gòu)化的表達(dá)式語言,但是Json的設(shè)計重點在于簡單易用、方便傳輸?shù)奶匦裕?br/>而 Yaml 則側(cè)重于可讀性(更加在乎外觀),幾乎可以把 Yaml 看做是 Json 的一個"超集",即可讀性更高(更漂亮) 的結(jié)構(gòu)化格式。
此外,Json更加便于生成和解析,適合在各種跨語言、分布式的環(huán)境中傳輸和交互;與此同時, Yaml 則一般只是用作的配置較多。

關(guān)于 Yaml 的定義可以訪問下面的地址:
http://www.yaml.org/spec/1.2/spec.html

二、Yaml 的語法

Yaml 是非常簡單的, 它所定義的元素只有三個:

  • 對象:就是鍵值對的集合,對應(yīng)于Java 中的 HashMap

  • 數(shù)組:指一組按序排列的值,對應(yīng)于Java 中的 List

  • 單值:單個的、不可再分的值,比如 3,"Jackson"

對象如何表示
一個對象的屬性、嵌套關(guān)系通過空格縮進對齊來表示,如下:

article:
    title: 一個人的自白書
    author:
        name: 陳玲
        gender: female

數(shù)組如何表示
數(shù)組的元素通過連接符(-)來表示,如下:

article:
    title: 一個人的自白書
    tags:
        - 傳記
        - 社會
        - 人物

構(gòu)成對象、數(shù)組內(nèi)容的基本單元是單值,Yaml支持的單個值的類型有七種,如下:

類型范例
字符串Bob
布爾值true
整數(shù)199
浮點數(shù)19.91
Null~
時間2001-12-14T22:14:09.10+08:00
日期2019-01-09

其中,日期、時間使用的是 ISO 8601 國際標(biāo)準(zhǔn)格式,關(guān)于它的定義可以參考:
https://www.w3.org/TR/NOTE-datetime

一般情況下單個值會在一行內(nèi)結(jié)束。但如果遇到多行的字符串,可以使用一些特殊字符表示,
比如:

text: |
  Hello
  World

對應(yīng)的結(jié)果為:

{ text: 'Hello\nWorld\n' }

可以用+表示保留字符串末尾的換行,-表示刪除字符串末尾的換行:

text1: |+
  Hello

text2: |-
  Hello

對應(yīng)的結(jié)果為:

{ text1: 'Hello\n\n\n', text2: 'Hello' }

除此之外,Yaml 還可以支持引用、函數(shù)、正則表達(dá)式等高級用法,但項目上一般很少用到。

三、操作 Yaml

Yaml如何理解

目前用來操作 Yaml 的常用組件是 Snake Yaml,這個庫支持標(biāo)準(zhǔn)的 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文件中添加:

<dependency>
    <groupId>org.yaml</groupId>
    <artifactId>snakeyaml</artifactId>
    <version>1.21</version>
</dependency>

B. 代碼片段

實現(xiàn)加載配置文件

如下面的代碼,實現(xiàn)了從類路徑config.yml文件中加載 yaml 配置內(nèi)容:

InputStream inputStream = YamlUtil.class.getClassLoader()
        .getResourceAsStream("config.yml");

Yaml yaml = new Yaml();
Map<String, Object> objectMap = yaml.load(inputStream);
System.out.println(objectMap.get("path"));

實現(xiàn)對象轉(zhuǎn)換

定義如下的Pojo 對象:

public static class A{
    private String name = "hello";
    private List<B> bs = new ArrayList<B>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<B> getBs() {
        return bs;
    }

    public void setBs(List<B> 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);

輸出結(jié)果如下:

bs:
- id: b3688f05-ea7e-436b-bc9a-9c5df555c7fd
- id: 7906224d-8ecc-43b8-bc3b-07985bc18ebd
name: hello

此時如果希望將Yaml 文本反過來轉(zhuǎn)換為 A 對象,可以執(zhí)行下面的代碼:

A a1 = new Yaml().parseToObject(aString, A.class);
...

C. 完整案例

最終,我們可以將 Yaml 文檔的操作封裝為一個工具類,方便在業(yè)務(wù)代碼中集成。

YamlUtil.java

public class YamlUtil {

    /**
     * 從資源文件加載內(nèi)容,并解析為Map對象
     *
     * @param path
     * @return
     */
    public static Map<String, Object> loadToMap(String path) {
        if (StringUtils.isEmpty(path)) {
            return Collections.emptyMap();
        }

        InputStream inputStream = YamlUtil.class.getClassLoader()
                .getResourceAsStream(path);

        Yaml yaml = new Yaml();
        Map<String, Object> objectMap = yaml.load(inputStream);
        return objectMap;
    }

    /**
     * 將字符串解析為Map對象
     *
     * @param content
     * @return
     */
    public static Map<String, Object> parseToMap(String content) {
        if (StringUtils.isEmpty(content)) {
            return Collections.emptyMap();
        }

        Yaml yaml = new Yaml();
        Map<String, Object> objectMap = yaml.load(content);
        return objectMap;
    }

    /**
     * 將字符串解析為類對象
     *
     * @param content
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T parseToObject(String content, Class<T> clazz) {
        if (StringUtils.isEmpty(content) || clazz == null) {
            return null;
        }

        Yaml yaml = new Yaml(new Constructor(clazz));
        T object = yaml.load(content);
        return object;
    }

    /**
     * 格式化對象
     *
     * @param object
     * @return
     */
    public static String format(Object object) {
        Yaml yaml = new Yaml();
        return yaml.dumpAsMap(object);
    }

}

至此,我們已經(jīng)完成了 Yaml 的讀寫。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI