Files
oneapp_docs/basic_utils/basic_config.md
2025-09-24 14:08:54 +08:00

12 KiB
Raw Blame History

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. 测试策略

  • 使用依赖注入进行单元测试
  • 模拟网络请求测试异常情况
  • 验证缓存行为的正确性

问题排查

常见问题

  1. 初始化失败: 检查配置JSON格式和依赖注入设置
  2. 正则匹配异常: 验证规则列表中的正则表达式语法
  3. 缓存不生效: 确认URL格式一致性

调试技巧

  • 启用详细日志查看配置加载过程
  • 使用basicConfigTag过滤相关日志
  • 检查版本解析是否符合x.x.x格式