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());
                }
            }
        });
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章