12 KiB
12 KiB
Basic Config - 基础配置管理模块文档
模块概述
basic_config 是 OneApp 基础工具模块群中的配置管理模块,提供了应用配置的统一管理、API服务管控、版本控制等功能。该模块采用领域驱动设计(DDD)架构,支持动态配置更新、服务白名单管理和API访问控制。
基本信息
- 模块名称: basic_config
- 模块路径: oneapp_basic_utils/basic_config
- 类型: Flutter Package Module
- 架构模式: DDD (Domain Driven Design)
- 主要功能: 配置管理、API服务管控、版本管理
核心特性
- API服务管控: 基于正则表达式的API路径匹配和访问控制
- 服务白名单: 支持白名单机制,允许特定服务绕过管控
- 动态配置更新: 支持运行时更新服务规则列表
- 版本管理: 内置版本比较和管理功能
- 缓存优化: 使用LRU缓存提升查询性能
- 项目隔离: 支持多项目代码隔离的配置管理
目录结构
basic_config/
├── lib/
│ ├── basic_config.dart # 模块入口文件
│ └── src/
│ ├── constants/ # 常量定义
│ │ └── module_constant.dart
│ ├── dependency/ # 依赖注入
│ │ └── i_config_deps.dart
│ ├── domains/ # 领域层
│ │ ├── basic_config_facade.dart # 配置门面服务
│ │ ├── entities/ # 实体对象
│ │ │ ├── config_service_failures.dart
│ │ │ ├── config_versions.dart
│ │ │ └── project_services.dart
│ │ ├── interfaces/ # 接口定义
│ │ │ └── app_api_services_interface.dart
│ │ └── value_objects/ # 值对象
│ │ └── project_code.dart
│ └── infrastructure/ # 基础设施层
│ └── repositories/
│ └── app_api_seervices_repository.dart
└── pubspec.yaml # 依赖配置
核心架构组件
1. 版本管理 (Version)
提供语义化版本号的解析和比较功能:
mixin Version {
/// 转成字符串格式
String get toStr => '$major.$minor.$revision';
/// 版本比较 - 大于
bool greaterThan(Version other) {
if (major > other.major) return true;
if (minor > other.minor && major == other.major) return true;
if (revision > other.revision &&
major == other.major &&
minor == other.minor) return true;
return false;
}
/// 主版本号
int get major;
/// 次版本号
int get minor;
/// 修订版本号
int get revision;
@override
String toString() => toStr;
/// 解析版本字符串 (格式: x.x.x)
static Version parseFrom(String versionStr) {
final split = versionStr.split('.');
if (split.length != 3) {
throw UnsupportedError('parse version From $versionStr failed');
}
final int major = int.parse(split[0]);
final int minor = int.parse(split[1]);
final int revision = int.parse(split[2]);
return _VersionImpl(major, minor, revision);
}
}
2. 项目服务实体 (ProjectServicesDo)
定义单个项目的服务配置信息:
class ProjectServicesDo {
/// 构造函数
/// [projectCode] 项目编号
/// [ruleList] api path 正则规则
/// [disableServiceList] 下架的服务列表
ProjectServicesDo({
required this.projectCode,
required this.ruleList,
required this.disableServiceList,
}) : _ruleListRegex = ruleList.map(RegExp.new).toList(growable: false);
/// 项目编号
final ProjectCodeVo projectCode;
/// 该项目对应的规则列表
final List<String> ruleList;
/// 对应正则表达式
final List<RegExp> _ruleListRegex;
/// 下架的服务
final List<String> disableServiceList;
/// 检查路径是否匹配规则
bool isMatchBy(String s) {
bool match = false;
for (final rule in _ruleListRegex) {
match = rule.hasMatch(s);
if (match) break;
}
return match;
}
}
3. 应用项目管理 (AppProjectsDo)
管理所有项目的服务配置:
class AppProjectsDo {
/// 构造函数
AppProjectsDo(this.version, this.projects) {
for (final project in projects) {
_projectsMap[project.projectCode.id] = project;
}
}
/// 版本号
final int version;
/// app所有项目的信息
List<ProjectServicesDo> projects;
/// 项目映射表
final Map<String, ProjectServicesDo> _projectsMap = {};
/// 根据项目代码查找项目
ProjectServicesDo? findBy(String projectCode) => _projectsMap[projectCode];
/// 检查服务是否已下架
bool isServiceDisabled({
required String projectCode,
required String service,
}) {
try {
final project = _projectsMap[projectCode];
project!.disableServiceList.firstWhere((e) => e == service);
return true;
} catch (e) {
return false;
}
}
/// 获取所有项目编号
List<String> getProjectCodes() => _projectsMap.keys.toList(growable: false);
}
4. 基础配置门面 (BasicConfigFacade)
核心配置管理服务,采用单例模式:
abstract class IBasicConfigFacade {
/// 初始化配置
Future<Either<ConfigServiceFailures, Unit>> initialize({
required String versionOfConnectivity,
String jsonServiceList = '',
List<String> whiteServiceList = const [],
IBasicConfigDeps? deps,
});
/// 检查API是否命中管控规则
Either<ConfigServiceFailures, bool> queryApiIfHit({
String projectCode = '',
String url = '',
});
/// 检查API是否在白名单
bool queryApiIfInWhiteList({required String url});
/// 主动更新服务规则列表
Future<bool> updateServiceList({List<String> projectCodes = const []});
/// 检查服务是否下架
bool isServiceDisabled({
required String projectCode,
required String service,
});
/// 根据项目代码查询项目信息
Either<ConfigServiceFailures, ProjectServicesDo> queryProjectBy({
String projectCode = '',
});
/// 获取当前连接版本
Version get currConnVersion;
}
/// 全局配置对象
IBasicConfigFacade basicConfigFacade = BasicConfigFacadeImpl();
5. 具体实现 (BasicConfigFacadeImpl)
class BasicConfigFacadeImpl implements IBasicConfigFacade {
BasicConfigFacadeImpl({IAppApiServiceRepo? appApiServiceRepo})
: _apiServiceRepo = appApiServiceRepo ?? ApiServiceListRepository();
static const String _tag = 'BasicConfigFacadeImpl';
final IAppApiServiceRepo _apiServiceRepo;
IBasicConfigDeps _deps = const DefaultConfigDeps();
final _cache = LruCache<String, bool>(storage: InMemoryStorage(20));
late Version _connVersion;
@override
Future<Either<ConfigServiceFailures, Unit>> initialize({
required String versionOfConnectivity,
String jsonServiceList = '',
List<String> whiteServiceList = const [],
IBasicConfigDeps? deps,
}) async {
if (deps != null) _deps = deps;
_connVersion = Version.parseFrom(versionOfConnectivity);
// 初始化api管控配置列表
final r = await _apiServiceRepo.initialize(
deps: _deps,
jsonServiceList: jsonServiceList,
whiteServiceList: whiteServiceList,
);
return r ? right(unit) : left(ConfigServiceFailures(
errorCodeConfigServiceInvalidLocalServiceList,
'initialize failed',
));
}
@override
Either<ConfigServiceFailures, bool> queryApiIfHit({
String projectCode = '',
String url = '',
}) {
final appProject = _apiServiceRepo.appProject;
if (appProject == null) {
return left(ConfigServiceFailures(
errorCodeConfigServiceEmptyServiceList,
'empty service list',
));
}
final findBy = appProject.findBy(projectCode);
if (findBy == null) return right(false);
// 使用缓存优化查询性能
final hitCache = _cache.get(url);
if (hitCache == null) {
final matchBy = findBy.isMatchBy(url);
_cache.set(url, matchBy);
return right(matchBy);
}
return right(hitCache);
}
// 其他方法实现...
}
使用指南
1. 初始化配置
import 'package:basic_config/basic_config.dart';
// 初始化基础配置
await basicConfigFacade.initialize(
versionOfConnectivity: '1.0.0',
jsonServiceList: jsonConfigData,
whiteServiceList: ['api/health', 'api/version'],
);
2. API访问控制
// 检查API是否命中管控规则
final result = basicConfigFacade.queryApiIfHit(
projectCode: 'oneapp_main',
url: '/api/user/profile',
);
result.fold(
(failure) => print('查询失败: ${failure.message}'),
(isHit) => {
if (isHit) {
print('API被管控,需要特殊处理')
} else {
print('API正常访问')
}
},
);
3. 白名单检查
// 检查API是否在白名单
bool inWhiteList = basicConfigFacade.queryApiIfInWhiteList(
url: '/api/health'
);
if (inWhiteList) {
// 白名单API,直接放行
print('白名单API,允许访问');
}
4. 服务状态检查
// 检查服务是否下架
bool isDisabled = basicConfigFacade.isServiceDisabled(
projectCode: 'oneapp_main',
service: 'user_profile',
);
if (isDisabled) {
// 服务已下架,显示维护页面
showMaintenancePage();
}
5. 动态更新配置
// 更新服务规则列表
bool updateSuccess = await basicConfigFacade.updateServiceList(
projectCodes: ['oneapp_main', 'oneapp_car'],
);
if (updateSuccess) {
print('配置更新成功');
}
6. 版本管理
// 版本解析和比较
Version currentVersion = Version.parseFrom('1.2.3');
Version newVersion = Version.parseFrom('1.2.4');
if (newVersion.greaterThan(currentVersion)) {
print('发现新版本: ${newVersion.toStr}');
// 执行更新逻辑
}
配置文件格式
服务配置JSON格式
{
"version": 1,
"projects": [
{
"projectCode": "oneapp_main",
"ruleList": [
"^/api/user/.*",
"^/api/payment/.*"
],
"disableServiceList": [
"old_payment_service",
"deprecated_user_api"
]
},
{
"projectCode": "oneapp_car",
"ruleList": [
"^/api/vehicle/.*",
"^/api/charging/.*"
],
"disableServiceList": []
}
]
}
依赖配置
pubspec.yaml 关键依赖
dependencies:
flutter:
sdk: flutter
# 函数式编程支持
dartz: ^0.10.1
# 基础日志模块
basic_logger:
path: ../basic_logger
# 基础存储模块
basic_storage:
path: ../basic_storage
dev_dependencies:
flutter_test:
sdk: flutter
架构设计原则
1. DDD分层架构
- Domain层: 包含业务实体、值对象和领域服务
- Infrastructure层: 处理数据持久化和外部服务调用
- Application层: 通过Facade模式提供应用服务
2. 函数式编程
- 使用
dartz包提供的Either类型处理错误 - 避免异常抛出,通过类型系统表达可能的失败情况
3. 依赖注入
- 通过接口定义依赖,支持测试替换
- 使用抽象类定义服务边界
性能优化
1. 缓存策略
- 使用LRU缓存存储API匹配结果
- 缓存大小限制为20个条目,避免内存过度使用
2. 正则表达式优化
- 预编译正则表达式,避免重复编译开销
- 使用不可变列表存储编译后的正则
3. 查询优化
- 使用Map结构优化项目查找性能
- 短路求值减少不必要的匹配操作
最佳实践
1. 错误处理
// 推荐:使用Either处理可能的错误
final result = basicConfigFacade.queryApiIfHit(
projectCode: projectCode,
url: url,
);
result.fold(
(failure) => handleFailure(failure),
(success) => handleSuccess(success),
);
// 不推荐:使用try-catch
try {
final result = riskyOperation();
handleSuccess(result);
} catch (e) {
handleError(e);
}
2. 配置管理
- 在应用启动时初始化配置
- 定期检查和更新远程配置
- 为关键服务提供降级策略
3. 测试策略
- 使用依赖注入进行单元测试
- 模拟网络请求测试异常情况
- 验证缓存行为的正确性
问题排查
常见问题
- 初始化失败: 检查配置JSON格式和依赖注入设置
- 正则匹配异常: 验证规则列表中的正则表达式语法
- 缓存不生效: 确认URL格式一致性
调试技巧
- 启用详细日志查看配置加载过程
- 使用
basicConfigTag过滤相关日志 - 检查版本解析是否符合x.x.x格式