NET2Java之六:項目配置

項目配置

.NET中的項目配置文件主要是.config和.json文件;而java中則主要是.properties和.yml文件,一般放在resource目錄下,maven項目則通常放在resources項目下。

本地配置

properties

properties文件是java早期的配置文件格式,鍵值對格式,使用等號或冒號分隔,以“#”和“!”作爲註釋。

#名稱
app.id:1
app.name=示例項目 

讀取:

    Properties properties = new Properties();
    InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("app.properties");

    //這裏是爲了防止中文亂碼
    properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

    System.out.println(properties.get("app.id"));
    System.out.println(properties.get("app.name").toString().length());

我覺得初次上手最容易忽視的反而是空格的問題,雖然不起眼,但極有可能會帶來大麻煩。

yml

雖然key-value的配置方式在絕大多數的場景下已經夠用,但處理複雜的配置結構則有些繁瑣,這時候則可以選擇yaml,其結構更爲清晰,並支持列表、字典等複雜的數據結構,特性如下:

  1. 大小寫敏感,也就是說username和userName是兩個東西;
  2. 使用縮進表示層級關係,縮進不允許使用tab,只允許使用空格,縮進的空格數不重要,同層級的元素左對齊即可;
  3. 使用“#”表示註釋。

yaml支持三種數據類型:

純量
簡單變量,支持字符、布爾、整數、Null等。

id: 1 # 整數
name: 張三 # 字符串默認不用引號,單包含空格或特殊字符則必須加引號,單引號或雙引號均可
gender: ~ # Null
birthday: 2000-01-01T00:00:00.10+08 #ISO8601標準時間

對象
鍵值對集合,如:

user: {id: 1,name: 張三}

當然還有另外一種寫法:

user:
  id: 1
  name: 張三

數組

fruits: [ 蘋果,香蕉,橘子,梨,葡萄 ]

另一種寫法則是以“-”開頭,表示數組中的一項:

fruits:
  - 蘋果
  - 香蕉
  - 橘子
  - 梨
  - 葡萄

結合對象的例子,我們展示一個user數組:

users:
  - id: 1
    name: 張三
  - id: 2
    name: 李四

讀取yml文件需要snakeyaml,maven依賴如下:

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

配置讀取代碼如下:

    InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("app.yml");
    Yaml yaml = new Yaml();
    Map<String, Object> map = yaml.loadAs(inputStream, Map.class);
    map.forEach((String key, Object val) -> {
        System.out.println("鍵:" + key + "\t值:" + val);
    });

如果只使用純量的話,使用Map就夠了,但如果對象比較複雜,則需要轉爲爲javabean:

id: 1 # 整數
name: 張三 # 字符串默認不用引號,單包含空格或特殊字符則必須加引號,單引號或雙引號均可
gender: ~ # Null
birthday: 2000-01-01T00:00:00.10+08 #ISO8601標準時間
tags: [ 高, 富, 帥 ]
userDetail: { schoolName: 山河大學,className: 三年級1班 }

User.java

package em.im.pve;

import lombok.*;

import java.util.Date;

@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    int id;
    String name;
    String gender;
    Date birthday;
    String[] tags;
    UserDetail userDetail;
}

UserDetail.java

package em.im.pve;


import lombok.*;

@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class UserDetail {
    String schoolName;
    String className;
}

Apollo客戶端

使用配置文件雖然可以非常靈活的修改配置,但業務分佈式部署時,尤其量級達到幾十上百臺時,變更配置極爲困難,也不便於管理,爲此,我們需要一個配置管理中心,集中管理。

官網:https://www.apolloconfig.com/#/zh/README

不過官方文檔寫的一言難盡,客戶端想正常使用首先需要引入Maven依賴:

<!--攜程Apollo-->
<dependencys>
    <dependency>
        <groupId>com.ctrip.framework.apollo</groupId>
        <artifactId>apollo-client</artifactId>
        <version>1.9.1</version>
    </dependency>
    <dependency>
        <groupId>com.ctrip.framework.apollo</groupId>
        <artifactId>apollo-core</artifactId>
        <version>1.9.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.9.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>23.0</version>
    </dependency>
</dependencys>

如果引入不完整會拋出Provider com.ctrip.framework.apollo.internals.DefaultInjector could not be instantiated異常。

Apollo配置:

app:
  id: 14889
apollo:
  meta: http://apollo-test.em/
  cache-dir: D:\apolloconfigs\
  autoUpdateInjectedSpringProperties: true #是否開啓Spring參數自動更新
  env: UAT
  bootstrap:
    enabled: true #是否開啓Apollo
    eagerLoad:
      enabled: true #飢餓加載
  access-key:
    secret:

配置獲取:


import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;

/**
 * 配置中心。
 */
public class ConfigContainer {
    static Config config = ConfigService.getAppConfig();
    private static HashSet<String> apiToken = null;

    public static String getConfig(String key) {
        return config.getProperty(key, "");
    }

    /**
     * Apollo Change事件監聽。
     */
    public static void openChangeListener() {
        config.addChangeListener(new ConfigChangeListener() {
            @Override
            public void onChange(ConfigChangeEvent configChangeEvent) {
                System.out.println("Change for namespace " + configChangeEvent.getNamespace());
                for (String key : configChangeEvent.changedKeys()) {
                    ConfigChange change = configChangeEvent.getChange(key);
                    System.out.printf("Found change-key:%s,oldValue:%s,newValue:%s%n", change.getPropertyName(), change.getOldValue(), change.getNewValue());
                }
            }
        });
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章