細數Java項目中用過的配置文件(YAML篇)

靈魂拷問:YAML,在項目中用過沒?它與 properties 文件啥區別?

目前 SpringBoot、SpringCloud、Docker 等各大項目、各大組件,在使用過程中幾乎都能看到 YAML 文件的身影。

2017 年的時候,我才真正把 YAML 文件用到負責的項目中,當時用 YAML 文件主要是為 Sharding-JDBC 配置數據源以及分庫分表的規則。

 

 從實際項目中把 sharding-jdbc.yaml 文件抽出來,為了更清晰,進行了大量簡化,接下來就一同感受一下 YAML 的魅力

 

1. 初步感受 YAML 的魅力。

 

上圖配置的內容雖然還沒解釋,仔細去看配置,大體都能看明白。其實,這就是 YAML 比 properties 配置文件的優勢所在,層次感分明,配置有序,而且比較簡潔。

縱然配置已經很清晰,還是要稍微帶著看一看配置內容。

 

dev 是一個對象,對應於 Java 中的 Map,包含 datasources 和 tables 兩個屬性。其本身含義是開發環境配置,當然實際項目中也會有測試、准生產、生產的對應的配置。

datasources 屬性是一個數組,對應於 Java 中的 List,數組元素由 name、default 等 10 個屬性構成。其本身含義是數據源配置,因為涉及到分庫,所以會有好多庫要連接,圖中只列舉兩個資料庫;

tables 屬性也是一個數組,對應於 Java 中的 List,數組元素由 tableName、databaseCount 等 5 個屬性構成。其本身含義是要拆分表的規則配置,圖中只列舉一個項目基本資訊表。

 

按照常規思路,寫好配置文件,接下來就要校驗一下,再稍微格式化一下。

在這兒校驗Yaml文件:http://www.bejson.com/validators/yaml/

 

如上圖所示,YAML 文件校驗轉換之後,就真的太清晰啦!

不過,YAML 是很簡單,但是有些細節,在開發中還是要注意,否則入坑就難跳出(一旦入坑,真的不好跳出來,別問為什麼?一個空格難倒英雄漢,真心體會過)。

 

Tips:

1. 使用冒號加縮進的方式代表層級關係,使用短橫杠代表數組元素;

2. 注意縮進不允許使用「tab」鍵,只能使用空格鍵(曾經掉這個坑啦,記憶之深刻);

3. 縮進空格個數多少並不重要,只要相同層級的元素左對齊即可;

4. 如果冒號後跟著 value,一定要注意冒號後跟上空格呦!

5. YAML 大小寫很敏感。

 

有關 YAML 的更多規範,可以參考如下 pdf,本次不過多展開去講。

https://yaml.org/spec/1.2/spec.pdf

 

2. YAML 配置有了,該怎麼去解析呢?

 

在不同的程式語言中,都有很多三方工具可以解析 YAML 文件,而在 Java 項目可以用 SnakeYaml 進行解析,接下來就寫寫程式碼體驗一下 yaml 文件的解析。

首先引入依賴包(想用人家,就別想撇清關係!)

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

碼點程式碼(從原項目中直接拿來,為了清晰,索性只留解析 YAML 文件部分的程式碼,呈現給你)

import org.apache.commons.collections4.MapUtils;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author 一猿小講
 */
public class ShardingJdbcDataSource {
    private static LinkedHashMap<String, Object> profile;

    @SuppressWarnings("unchecked")
    public static ArrayList<LinkedHashMap<String, Object>> parse(String profileId, String key) throws IOException {
        //如果profile為空的情況才進行載入配置文件,減少讀取文件的次數
        if (MapUtils.isEmpty(profile)) {
            Yaml yaml = new Yaml();
            File file = new File(ShardingJdbcDataSource.class.getResource("/").getPath() + "sharding-jdbc.yaml");
            try (FileReader fileReader = new FileReader(file);) {
                Map<String, Object> result = yaml.loadAs(fileReader, Map.class);
                profile = (LinkedHashMap<String, Object>) result.get(profileId);
            }
        }
        return (ArrayList<LinkedHashMap<String, Object>>) profile.get(key);
    }

    public static void main(String[] args) throws IOException {
        // 開發環境
        String profileId = "dev";

        // 數據源集合
        ArrayList<LinkedHashMap<String, Object>> datasources = parse(profileId, "datasources");
        for (LinkedHashMap<String, Object> datasource : datasources) {
            System.out.println(String.format("資料庫名稱:%s",datasource.get("name")));
            System.out.println(String.format("資料庫URL:%s",datasource.get("jdbc.url")));
        }

        System.out.println("=============華麗的分割線==============");

        // 表集合
        ArrayList<LinkedHashMap<String, Object>> tables = parse(profileId, "tables");
        for (LinkedHashMap<String, Object> table : tables) {
            System.out.println(String.format("表名稱:%s",table.get("tableName")));
            System.out.println(String.format("資料庫拆分 %d 個",table.get("databaseCount")));
            System.out.println(String.format("每個資料庫表的數目:%s",table.get("tableCountPerDatabase")));
        }
    }
}

去掉 main 函數,發現解析程式碼沒幾行,跑起來看一看,效果還可以。

 

文中的解析 YAML 文件的程式碼,改個類名,就可以直接變成工具類,如果有需要,自行簡單封裝一下就 ok 啦。

其中 SnakeYaml 類庫還有很多 API 可以使用,不一一帶著寫程式碼啦,感興趣的自行參考 SnakeYaml 官方文檔,去照貓畫虎敲敲吧。

https://bitbucket.org/asomov/snakeyaml/wiki/Documentation

另外,細心的你在平時研發時,有沒有發現,有的項目 YAML 文件的後綴是 .yml,有的項目卻是 .yaml,到底哪個是正確的呢?很久很久之前我也糾結過,感興趣可以去 stackoverflow 溜達一番。

https://stackoverflow.com/questions/21059124/is-it-yaml-or-yml

 

3. 它山之石可以攻玉

在 Java 項目研發過程中,總會遇到一些經常改變的參數,比如要連接的資料庫的連接地址、名稱、用戶名、密碼;再比如訪問三方服務的 URL 等等。考慮到程式的通用性,這些參數往往不能直接寫死在程式里,通常藉助配置文件來優雅處理,而常用的配置文件多數為 Properties,而相對 Properties 而言 YAML 卻表現的更加層次分明。

好了,有關 YAML 文件在實際項目中的使用,本次就談到這裡,它山之石可以攻玉,希望能對你有所幫助。

Tags: