> 状态(2026-04-18 立项):**提案阶段,未实施** > 优先级:高。与 `add-mjava-com` 并行,共同承担"多用户/多客户使用支持"大方向。 ## Why 现有 `mjava-mcli` / `mjava-shunfeng` / `mjava-guangming` 三个客户子项目采用"一客户一 jar"模式,每次加新客户都要: 1. 复制 mcli 模板 → 改 artifactId / port / context-path 2. 在 `application-{profile}.yml` 硬编码该客户的 appKey/appSecret/corpId 3. 单独部署一个 JVM 实例 这种方式在客户数量少(≤ 5)时尚可,但问题: - 新客户上线 = 发布新版本 + 运维新增部署节点,交付周期慢 - 一客户一实例,资源利用率低 - appKey/appSecret 静态写在 yml,切换客户需要重启 + 重新发包 - 实例间没有共享缓存,每客户独立维护自己的 token 生命周期 需要一个支持"**一个 jar 同时服务多个客户**"的子项目模板 `mjava-pro`,按请求上下文动态加载客户配置、token 按租户隔离缓存,**加客户 = 新增一条宜搭应用表记录**,无需改代码和重启。 ## What Changes 新增子模块 `mjava-pro/`,具备以下能力: - **租户解析**:请求入口识别 `X-Tenant-Id` header(或 subdomain / path prefix,实现时选定),未识别到返回 401 - **应用配置动态加载**:从宜搭"应用表"(formUuid 配置在 `application.yml`)按 tenantId 查询 appKey / appSecret / corpId / 其他授权参数;命中后缓存到内存(TTL 可配,默认 10 分钟) - **Token 隔离**:`UtilToken` key 扩展为 `{tenant}:{vendor}:{appKey}`,各租户独立缓存不互相覆盖 - **Client 透传**:基座 `DDClient` / `YDClient` 等保持原签名不变;`mjava-pro` 内部通过 `TenantContext`(ThreadLocal)传 appKey/appSecret 进去 - **配置表结构约定**:宜搭应用表字段规范固定在 `spec.md` 中(tenantId / vendor / appKey / appSecret / extraJson / enabled / ...) ## Capabilities ### New Capabilities - `multi-tenant-runtime`:单部署多租户运行时,按请求上下文路由到对应客户配置 - `tenant-registry`:从宜搭应用表加载租户配置的注册中心抽象 ### Modified Capabilities ## Impact - **新增模块**:`mjava-pro/`(独立 jar,默认端口 9010,context-path `/api/pro`) - **新增代码**(预计): - `TenantContext.java` + `TenantInterceptor.java`(ThreadLocal 管理) - `TenantRegistryService.java`(查宜搭应用表) - `DynamicDDClientProxy.java`(包装基座 DDClient,按 tenant 注入凭据) - `application.yml` + `application-{dev,prod}.yml.example` - **基座影响**:可能需要 `UtilToken` 支持 key 命名空间;评估后若需要再开子提案 - **现有客户模块**:零影响,mcli/shunfeng/guangming 继续运行 - **部署**:单 pro jar 可接管 N 个客户,运维新增客户只在宜搭应用表加一行记录即可 ## Non-Goals - ❌ 不替代现有 mjava-mcli/shunfeng/guangming(已交付客户保持原架构) - ❌ 不引入 Redis(tenant 配置缓存仍走 `TimedCache`,单实例足够;若将来多实例再评估) - ❌ 不做跨租户数据聚合 / 租户级计费 / 多租户数据库分离 - ❌ 本提案不涵盖前端租户切换 UI(前端按现有方式各自管理)