## `rucfg` 目录解析
`rucfg` 是项目的**配置管理层**,负责加载 YAML 配置文件、解析环境变量占位符、并通过 DI 容器提供全局可访问的配置实例。
### 文件结构
```
rucfg/
├── mod.rs # 模块导出
├── ruconfig.rs # 核心配置结构 RuConfig
├── ruconfig_init.rs # RuConfig 的 DI 注册(自动生成)
├── parsecfg.rs # 配置文件解析辅助函数
└── ruconfig_test.rs # 配置相关测试
```
---
### 核心设计:`RuConfig`
[ruconfig.rs](file:///E:/soft/gitee.com/ruwebframe/src/rucfg/ruconfig.rs) 是配置管理的核心:
```rust
pub struct RuConfig {
parsed: AtomicBool, // 是否已解析(原子标志)
pub config: Arc<Mutex<CfgDto>>, // 配置数据(Arc + Mutex 保证线程安全)
}
```
**设计要点**:
- 使用 `Arc<Mutex<CfgDto>>` 包裹配置,支持多线程安全读写
- `AtomicBool` 标记解析状态,防止重复解析
- 实现了 `BaseEntity` trait(多实例模式),每次 `direg::get` 都创建新实例
---
### 配置加载流程
```
程序启动
│
▼
ruconfig_init.rs → ctor 自动注册 → direg::register("...", RuConfig::new)
│
▼
RuConfig::new()
│
├── 1. 创建 CfgDto::default() 默认配置
│
├── 2. parse_config() 解析正式配置
│ │
│ ├── parse_env2file() → 读取 /config/env.yml 获取当前环境名
│ │ ├── env = "dev" → /config/ichub-dev.yml
│ │ ├── env = "test" → /config/ichub-test.yml
│ │ └── env = "prod" → /config/ichub-prod.yml
│ │
│ ├── 读取对应的 YAML 文件
│ │
│ ├── serde_yaml::from_str::<CfgDto>() 反序列化
│ │
│ └── guard.parse_env_var() → 替换所有 ${VAR:default} 占位符
│
└── 3. parsed.store(true) 标记解析完成
```
---
### 关键方法一览
| `new()` | `RuConfig` | 构造函数,自动触发配置解析 |
| `read()` | `CfgDto`(克隆) | 获取配置的完整副本 |
| `readCfg()` | `MutexGuard<CfgDto>` | 获取配置的锁守卫(可修改) |
| `readEnv()` | `String` | 获取当前环境名(dev/test/prod) |
| `read2json()` | `String` | 配置转为 JSON 字符串 |
| `get_self()` | `CfgDto` | 通过 `GetSelf` trait 克隆配置 |
| `parse_config()` | — | 触发 YAML 文件解析 |
| `parse_env()` | `String` | 从 `env.yml` 读取 `Env` 字段 |
| `parse_env2file()` | `String` | 根据环境名拼接配置文件路径 |
| `get_config(file)` | `String` | 拼接完整配置文件路径 |
---
### 环境判断辅助函数
[ruconfig.rs](file:///E:/soft/gitee.com/ruwebframe/src/rucfg/ruconfig.rs) 提供了便捷的环境判断函数:
```rust
pub fn ifDev() -> bool // 当前是否为 dev 环境
pub fn ifTest() -> bool // 当前是否为 test 环境
pub fn ifMaster() -> bool // 当前是否为 prod/master 环境
pub fn ifNotMaster() -> bool // 当前是否非生产环境
pub fn findEnv() -> String // 获取当前环境名
```
这些函数内部统一调用 `rucfg::find_bean_ruconfig().unwrap().readEnv()`。
---
### `parsecfg.rs` — 解析辅助函数
[parsecfg.rs](file:///E:/soft/gitee.com/ruwebframe/src/rucfg/parsecfg.rs) 提供了独立的配置解析工具函数,不依赖 `RuConfig` 实例:
| `parse_env()` | 直接读取 `env.yml` 获取环境名 |
| `parse_env_var(var)` | 委托 `strutils::parse_env_var` 解析 `${VAR:default}` |
| `parse_env2file()` | 环境名 → 配置文件名(如 `dev` → `ichub-dev.yml`) |
| `parse_cfg2file(fileName)` | 解析指定 YAML 文件中的 `software.env` 字段 |
| `parse_config()` | 直接解析 `ichub-postgres.yml`(硬编码路径,用于测试) |
---
### DI 注册方式
[ruconfig_init.rs](file:///E:/soft/gitee.com/ruwebframe/src/rucfg/ruconfig_init.rs) 是自动生成的 DI 注册代码:
```rust
// 多例模式(register 而非 register_singleton)
direg::register(SINGLE_BEAN_NAME, RuConfig::new);
// 获取方式
pub fn find_bean_ruconfig() -> Option<Arc<RuConfig>> {
direg::get_bean::<RuConfig>(SINGLE_BEAN_NAME)
}
```
注意这里是**多例模式**(`register`),每次 `get_bean` 都会调用 `RuConfig::new()`,从而重新解析配置。但 `CfgDto` 本身也有自己的 DI 注册(`cfgdto_init.rs`),使用单例模式。
---
### 使用示例
来自 [ruconfig_test.rs](file:///E:/soft/gitee.com/ruwebframe/src/rucfg/ruconfig_test.rs):
```rust
// 1. 读取完整配置
let config = rucfg::find_bean_ruconfig().unwrap().read();
println!("{:#?}", config);
// 2. 配置转 JSON
let json = rucfg::find_bean_ruconfig().unwrap().read2json();
// 3. 修改配置并序列化
let mut config = rucfg::find_bean_ruconfig().unwrap().read();
config.gorm.dbType = "postgres".to_string();
let pp = config.from_json(config.to_json()); // 深拷贝
// 4. 环境判断
if rucfg::ifMaster() {
// 生产环境逻辑
}
```
---
### 配置数据流图
```
/config/env.yml /config/ichub-{env}.yml
┌────────────────┐ ┌──────────────────────────┐
│ Env: dev │ ─── 环境名 ──→ │ software: │
└────────────────┘ │ env: dev │
│ gorm: │
│ dbType: ${DB_TYPE:pg} │ ← 环境变量占位符
│ datasource: │
│ host: ${DB_HOST:local} │
│ password: enc(xxx) │ ← 加密密码
│ redis: │
│ addr: ... │
└──────────┬───────────────┘
│
serde_yaml::from_str::<CfgDto>()
│
▼
┌─────────────────────┐
│ CfgDto │
│ parse_env_var() │ ← 替换占位符 + 解密
└──────────┬──────────┘
│
Arc<Mutex<CfgDto>> ← 线程安全共享
│
┌──────────┴──────────┐
│ RuConfig │
│ read() / readCfg() │
└──────────────────────┘
```
---
### 架构定位
```
┌──────────┐
│ rubase │ ← 提供 CfgDto 结构定义、strutils 环境变量解析、ruenc 解密
└────┬─────┘
│ 依赖
▼
┌──────────┐
│ rucfg │ ← 配置加载、解析、全局访问
└────┬─────┘
│ 被依赖
▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ database │ │ rudomain │ │ ruweb │ ← 各模块通过 rucfg::find_bean_ruconfig() 获取配置
└──────────┘ └──────────┘ └──────────┘
```
**总结**:`rucfg` 是项目的配置中枢,它从 YAML 文件加载配置,自动解析环境变量占位符和加密字段,通过 `Arc<Mutex<CfgDto>>` 保证线程安全,并利用 DI 容器提供全局可访问的配置实例。所有需要配置的模块(数据库、Redis、Web 服务等)都通过它获取运行参数。