## 1. 模块脚手架 - [x] 1.1 新建 `mjava-pro/`(非直接 cp mcli,精简依赖) - [x] 1.2 `pom.xml` artifactId=mjava-pro,依赖仅 mjava 基座 - [x] 1.3 `Boot.java` package=com.malk.pro,`@EnableScheduling` + `@EnableJpaAuditing` + scanBasePackages=com.malk - [x] 1.4 `application.yml` port=9010 / context-path=/api/pro / spel.scheduling=true / multiSource=false - [x] 1.5 根 `pom.xml` `` 追加 `mjava-pro` - [x] 1.6 `mvn -pl mjava-pro -am compile` 通过(2026-04-19 验证) ## 2. TenantContext 核心 - [x] 2.1 `TenantProfile` + `VendorCredential` 数据类 - [x] 2.2 `TenantContext`(ThreadLocal + set/current/clear/propagate + currentTenantId) - [x] 2.3 `TenantInterceptor`(preHandle 读 X-Tenant-Id → registry.get → TenantContext.set + MDC;afterCompletion clear;401 TENANT_REQUIRED / 403 TENANT_NOT_FOUND) - [x] 2.4 `ProWebConfig` 注册拦截器,排除 /_admin/** / /actuator/** / /static/** 等 - [ ] 2.5 TenantTaskDecorator(@Async 传播)— 延后,首次生产启用时评估 ## 3. TenantRegistry - [x] 3.1 `TenantRegistryService`(依赖 `YDClient_Form`,使用新原子接口 searchForm) - [x] 3.2 `loadAll()` 按 formUuid 分页查宜搭应用表 → mergeRow 合并同 tenantId 多 vendor → `Map` - [x] 3.3 `get(tenantId)` / `contains` / `size` 内存 Map 直查(缓存 miss 不触发单条拉取,等下次 TTL 刷新) - [x] 3.4 `@PostConstruct init()` + `@Scheduled(fixedDelayString=ttl*1000)` 定时刷新;failFast 开关控制启动失败行为 - [x] 3.5 `AdminController` `@Profile("dev") @NoAuth POST /_admin/reloadTenant` ## 4. Client / Service 透传 - [ ] 4.1 新建 `com.malk.pro.service.dingtalk.DynamicDDService`:从 `TenantContext` 读凭据 → 构造 `DDConf` → 调基座 `DDClient` - [ ] 4.2 同法建 `DynamicYDService`(对接宜搭)、其他 vendor 按需 - [ ] 4.3 `UtilToken` 使用规范:key 统一 `{tenantId}:{vendor}:{appKey}`(若基座未扩展 namespace,就在调用侧拼) ## 5. 审计日志 - [ ] 5.1 `UtilHttp` 审计日志扩展字段 `tenantId`(从 MDC 读);改基座或在 pro 侧包一层 - [ ] 5.2 logback-spring.xml 为 mjava-pro 独立输出 `./log/{日期}/pro-%X{tenantId}.log` - [ ] 5.3 确保异步线程能读到 MDC(配合 Task 2.5) ## 6. 配置与文档 - [ ] 6.1 `application-dev.yml.example`(含 tenant.registry.* 占位) - [ ] 6.2 `application-prod.yml.example`(含 tenant.registry.* 占位) - [ ] 6.3 `README.md`(在 mjava-pro 目录下,说明新增租户操作步骤) - [ ] 6.4 更新 `/Users/malk/Desktop/Tech/claude/后端/mjava-baseline.md` 表格里 mjava-pro 状态改为"已实施" ## 7. 验证 - [ ] 7.1 单元测试:`TenantContextTest`(set/clear/异步传播) - [ ] 7.2 集成冒烟:两个租户配置 → 用不同 `X-Tenant-Id` 调同一接口 → 验证 token 隔离 + 审计日志分片 - [ ] 7.3 压测:100 QPS 下 TenantContext 无泄漏(ThreadLocal clear 正确) - [ ] 7.4 `/opsx:validate add-mjava-pro --strict` 通过