Skip to content

EnvUtils 配置工具 ​

EnvUtils 是 tio-utils 提供的统一配置管理工具,用于在应用运行时,从多个配置来源中获取配置值,并按照固定优先级进行解析与覆盖。

它解决的核心问题是:

  • 配置来源分散(参数、环境变量、配置文件)
  • 多环境配置切换复杂
  • 本地个性化配置容易污染团队环境

EnvUtils 通过一套明确的加载规则和优先级模型,统一了这些行为。


一、配置来源与优先级 ​

EnvUtils 在读取某个配置项时,会按以下优先级依次查找,先命中即返回:

  1. 内部配置 Map

    • 通过 EnvUtils.set(key, value) 设置
    • 优先级最高,可覆盖一切其他来源
  2. 命令行参数

    • 格式:--key=value
  3. Java 系统属性

    • JVM 启动参数:-Dkey=value
  4. 系统环境变量

    • 先查原始 key
    • 再查自动转换后的大写下划线形式 例如:jdbc.pswd → JDBC_PSWD
  5. 配置文件

    • 由 PropUtils 统一加载和管理

这一优先级模型保证了:

  • 运行时参数 > 启动参数 > 环境变量 > 文件配置
  • 本地或临时调整不会影响仓库内配置文件

二、配置文件加载机制 ​

1. 默认加载方式 ​

java
EnvUtils.load();

这是独立工具程序最常用的方式,其加载规则如下。使用 TioApplication.run 的应用不要提前调用它,原因见配置参数。

1.1 主配置文件 ​

  1. 优先在 classpath 中查找 app.properties

  2. 如果存在:

    • 自动按 app.env 加载主配置 + 环境配置 等价于:

      • app.properties
      • app-{env}.properties(如果存在)
  3. 如果 classpath 中不存在:

    • 若已设置 app.env,尝试加载 app-{env}.properties
    • 否则尝试加载当前目录下的 app.properties

1.2 附加配置文件(append 模式) ​

以下文件会追加加载,且后加载的覆盖前面的值:

加载顺序固定为:

  1. ~/.env 和 ~/secrets.txt(用户目录下的配置文件)
  2. app.properties(classpath 中存在则加载)
  3. app.properties(当前工作目录中存在则加载)
  4. .env(classpath 中存在则加载)
  5. .env(当前工作目录中存在则加载)
  6. secrets.txt(当前工作目录)
  7. my.txt(当前工作目录,在文件配置中最后加载;仍低于内部 Map、命令行参数、Java 系统属性和系统环境变量)

文件读取结果保存在 PropUtils 中,不同文件不是 EnvUtils.get 的独立查找层级。追加加载仅覆盖同名 key。

业务代码统一使用 EnvUtils.get("ALIPAY_APP_ID") 等方法读取配置,避免绕过上述优先级。私钥建议使用配置指定的本地文件路径,不要将密钥写入源码或日志。

1.3 推荐实践 ​

  • app.properties

    • 放通用配置、框架级配置
  • .env / secrets.txt

    • 放密钥、密码、敏感信息
  • my.txt

    • 本地个人配置
    • 不提交到 git,用于个人调试,避免污染他人环境

2. 指定配置文件名 ​

java
EnvUtils.load("custom.properties");

适用于非标准命名的配置文件。


3. 指定环境 + 文件名 ​

java
EnvUtils.load("dev", "app.properties");

适用于需要显式控制环境的场景。


三、配置值读取 API ​

EnvUtils 提供了一组类型安全的静态方法。

1. 字符串 ​

java
String v1 = EnvUtils.get("config.key");
String v2 = EnvUtils.get("config.key", "default");

2. int / Integer ​

注意区分 基本类型 和 包装类型:

java
int v1 = EnvUtils.getInt("config.int");          // 不存在返回 0
int v2 = EnvUtils.getInt("config.int", 10);

Integer v3 = EnvUtils.getInteger("config.int"); // 不存在返回 null
Integer v4 = EnvUtils.getInteger("config.int", 10);

设计原则是:

  • getInt 适合业务上“必须有值”的场景
  • getInteger 适合区分“未配置”和“配置为 0”的场景

3. Long ​

java
Long v1 = EnvUtils.getLong("config.long");
Long v2 = EnvUtils.getLong("config.long", 100L);

4. boolean ​

java
boolean b1 = EnvUtils.getBoolean("feature.enable");
boolean b2 = EnvUtils.getBoolean("feature.enable", true);

四、环境管理(app.env) ​

EnvUtils 使用 app.env 作为当前运行环境标识。

1. 获取当前环境 ​

java
String env = EnvUtils.getAppEnv(); // 或 EnvUtils.env()

2. 环境判断快捷方法 ​

java
EnvUtils.isDev();
EnvUtils.isLocal();
EnvUtils.isTest();
EnvUtils.isStage();
EnvUtils.isPreview();
EnvUtils.isProd();

3. 切换环境 ​

java
EnvUtils.useDev();
EnvUtils.use("custom");

本质是设置一个最高优先级的内部配置值。


五、运行时覆盖配置(最高优先级) ​

java
EnvUtils.set("server.port", "9090");

通过 set 设置的值:

  • 不依赖任何外部来源
  • 在整个生命周期内优先级最高
  • 常用于测试、嵌入式场景或动态调整

六、命令行参数支持 ​

EnvUtils 支持解析以下格式的启动参数:

text
--key=value

使用方式:

java
public static void main(String[] args) {
    EnvUtils.buildCmdArgsMap(args);
    EnvUtils.load();
}

解析后的参数自动参与配置查找流程。


七、环境变量自动转换规则 ​

在读取系统环境变量时,会进行两次查找:

  1. 原始 key

  2. 转换后的 key:

    • . → _
    • 全部转为大写

示例:

text
jdbc.pswd  →  JDBC_PSWD

因此在容器、CI/CD 或系统层面配置时,可以使用更符合平台习惯的变量名。


八、日志行为 ​

EnvUtils 在加载配置时会输出关键日志,包括:

  • 实际加载了哪些配置文件
  • 当前 app.env
  • 应用名称(如存在)

日志基于 SLF4J,便于在启动阶段快速确认配置来源是否符合预期。


九、依赖说明 ​

EnvUtils 本身依赖以下工具类:

  • PropUtils:配置文件加载与合并
  • ResourceUtil:classpath 资源查找

请确保它们在项目中可用。


总结 ​

EnvUtils 的设计目标是:

  • 配置来源清晰
  • 优先级确定
  • 多环境可控
  • 本地配置安全、不污染团队

在中大型 Java 应用、微服务、CLI 工具中,都可以作为统一配置入口使用。

MIT Licensed