## 1. 模块脚手架 - [ ] 1.1 复制 `mjava-mcli/` 为 `mjava-pro/` - [ ] 1.2 改 `pom.xml` artifactId 为 `mjava-pro` - [ ] 1.3 改 `Boot.java` package 为 `com.malk.pro`,`scanBasePackages = {"com.malk"}` 保持 - [ ] 1.4 改 `application.yml` server.port=9010 + context-path=/api/pro;spel.multiSource=false - [ ] 1.5 根 `pom.xml` `` 追加 `mjava-pro` - [ ] 1.6 `mvn -pl mjava-pro -am compile` 通过 ## 2. TenantContext 核心 - [ ] 2.1 新建 `mjava-pro/src/main/java/com/malk/pro/tenant/TenantProfile.java`(数据类:tenantId + vendorCredentials + extraJson) - [ ] 2.2 新建 `com.malk.pro.tenant.TenantContext`(`ThreadLocal` + `current()/set()/clear()/propagate()`) - [ ] 2.3 新建 `TenantInterceptor`(`HandlerInterceptor`)解析 `X-Tenant-Id` → 查注册表 → set;afterCompletion clear - [ ] 2.4 在 `WebMvcConfigurer` 注册拦截器,排除 `/_admin/**` 的公共端点 - [ ] 2.5 扩展 `MdcTaskDecorator` 或新建 `TenantTaskDecorator`,挂到 `AsyncConfig` 两个线程池 ## 3. TenantRegistry - [ ] 3.1 新建 `com.malk.pro.tenant.TenantRegistryService`(依赖 `YDClient`) - [ ] 3.2 实现 `loadAll()`:按 `tenant.registry.formUuid` 分页查宜搭应用表,转 `TenantProfile` - [ ] 3.3 实现 `get(tenantId)`:内存 Map 查;缺失触发 `loadOne()` 单条拉取 - [ ] 3.4 `@PostConstruct loadAll()`;`@Scheduled(fixedDelay = ttl)` 异步刷新 - [ ] 3.5 新建 `AdminController`(仅 dev profile 通过 `@Profile("dev")` 生效)暴露 `/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` 通过