From fccadf63c2c38cb96e1a9fe9d5b2ede8cd100ebb Mon Sep 17 00:00:00 2001 From: zhangjf Date: Sun, 15 Feb 2026 11:42:20 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9E=B6=E6=9E=84=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E8=A1=A5=E5=85=85=E7=BB=9F=E4=B8=80=E5=85=A8=E5=B1=80=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87GlobalContext=EF=BC=8C=E7=BB=9F=E7=AD=B9tid/u?= =?UTF-8?q?id/uname=E8=8E=B7=E5=8F=96=E5=92=8C=E5=BC=82=E6=AD=A5=E4=BC=A0?= =?UTF-8?q?=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/资金服务平台 FundPlatform 架构设计文档.md | 166 +++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/doc/资金服务平台 FundPlatform 架构设计文档.md b/doc/资金服务平台 FundPlatform 架构设计文档.md index 865cdb5..949e586 100644 --- a/doc/资金服务平台 FundPlatform 架构设计文档.md +++ b/doc/资金服务平台 FundPlatform 架构设计文档.md @@ -1240,8 +1240,171 @@ public class ReactiveContextFilter implements WebFilter { } ``` -**原 5. 用户上下文管理(已升级为支持异步的版本)** +**5. 统一全局上下文管理(GlobalContext)** +为了统一管理和传递全局参数(tid、uid、uname、traceId 等),设计一个综合的 GlobalContext: + +```java +/** + * 全局上下文持有者 + * 统一管理租户ID、用户ID、用户名、TraceId等全局参数 + * 支持同步和异步场景 + */ +public class GlobalContext { + + // ========== 全局参数键名 ========== + public static final String KEY_TENANT_ID = "tid"; + public static final String KEY_USER_ID = "uid"; + public static final String KEY_USERNAME = "uname"; + public static final String KEY_TRACE_ID = "traceId"; + public static final String KEY_TENANT_GROUP = "tgroup"; + + // ========== ThreadLocal 存储 ========== + private static final ThreadLocal> CONTEXT = ThreadLocal.withInitial(HashMap::new); + + // ========== 全局上下文载体(支持异步传递)========== + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ContextSnapshot { + private String tenantId; + private Long userId; + private String username; + private String traceId; + private String tenantGroup; + private Map extra; + + public static ContextSnapshot create() { + return ContextSnapshot.builder() + .tenantId(getTenantId()) + .userId(getUserId()) + .username(getUsername()) + .traceId(getTraceId()) + .tenantGroup(getTenantGroup()) + .extra(new HashMap<>(getAll())) + .build(); + } + + public void apply() { + if (tenantId != null) set(KEY_TENANT_ID, tenantId); + if (userId != null) set(KEY_USER_ID, userId); + if (username != null) set(KEY_USERNAME, username); + if (traceId != null) set(KEY_TRACE_ID, traceId); + if (tenantGroup != null) set(KEY_TENANT_GROUP, tenantGroup); + if (extra != null) extra.forEach((k, v) -> { + if (!CONTEXT.get().containsKey(k)) set(k, v); + }); + } + } + + // ========== 基础操作 ========== + @SuppressWarnings("unchecked") + public static T get(String key) { return (T) CONTEXT.get().get(key); } + + public static void set(String key, Object value) { + CONTEXT.get().put(key, value); + if (value != null) MDC.put(key, String.valueOf(value)); + } + + public static void clear() { + CONTEXT.get().clear(); + MDC.clear(); + } + + // ========== 便捷方法 ========== + public static String getTenantId() { return get(KEY_TENANT_ID); } + public static void setTenantId(String tenantId) { set(KEY_TENANT_ID, tenantId); } + + public static Long getUserId() { + Object uid = get(KEY_USER_ID); + return uid instanceof String ? Long.valueOf((String) uid) : (Long) uid; + } + public static void setUserId(Long userId) { set(KEY_USER_ID, userId); } + + public static String getUsername() { return get(KEY_USERNAME); } + public static void setUsername(String username) { set(KEY_USERNAME, username); } + + public static String getTraceId() { return get(KEY_TRACE_ID); } + public static void setTraceId(String traceId) { set(KEY_TRACE_ID, traceId); } + + // ========== 异步场景支持 ========== + public static ContextSnapshot snapshot() { return ContextSnapshot.create(); } + + public static Runnable wrap(Runnable runnable) { + ContextSnapshot snapshot = snapshot(); + return () -> { try { snapshot.apply(); runnable.run(); } finally { clear(); } }; + } + + public static Callable wrap(Callable callable) { + ContextSnapshot snapshot = snapshot(); + return () -> { try { snapshot.apply(); return callable.call(); } finally { clear(); } }; + } + + public static Supplier wrap(Supplier supplier) { + ContextSnapshot snapshot = snapshot(); + return () -> { try { snapshot.apply(); return supplier.get(); } finally { clear(); } }; + } + + public static CompletableFuture supplyAsync(Supplier supplier, Executor executor) { + return CompletableFuture.supplyAsync(wrap(supplier), executor); + } + + public static CompletableFuture runAsync(Runnable runnable, Executor executor) { + return CompletableFuture.runAsync(wrap(runnable), executor); + } +} +``` + +**6. GlobalContext 使用示例** + +```java +// 同步场景 +@Service +public class ProjectService { + public void createProject(ProjectDTO dto) { + String tid = GlobalContext.getTenantId(); + Long uid = GlobalContext.getUserId(); + String uname = GlobalContext.getUsername(); + + log.info("[{}] 租户 {} 用户 {} 创建项目", tid, uname); + + Project project = new Project(); + project.setTenantId(tid); + project.setCreatedBy(uid); + projectMapper.insert(project); + } +} + +// 异步场景 +@Service +public class AsyncService { + @Autowired private ThreadPoolExecutor executor; + + public void asyncProcess(Long projectId) { + executor.execute(GlobalContext.wrap(() -> { + String tid = GlobalContext.getTenantId(); + Long uid = GlobalContext.getUserId(); + String uname = GlobalContext.getUsername(); + + log.info("[Async] 租户 {} 用户 {} 处理项目 {}", tid, uname, projectId); + + Project project = projectMapper.selectById(projectId); + project.setProcessedBy(uid); + projectMapper.updateById(project); + })); + } + + public CompletableFuture asyncQuery(Long projectId) { + return GlobalContext.supplyAsync(() -> { + log.info("[Async] 用户 {} 查询项目 {}", GlobalContext.getUsername(), projectId); + return projectMapper.selectById(projectId); + }, executor); + } +} +``` + +**原 5. 用户上下文管理(已合并到 GlobalContext)** **7. 调用链上下文过滤器(接收方)** @@ -2971,6 +3134,7 @@ fund-sys/ | v1.1 | 2026-02-13 | 补充多租户架构(一库多租户/一库一租户)和 Head 日志追踪设计 | zhangjf | | v1.2 | 2026-02-13 | 补充 Shiro 认证框架、服务调用链 uid/uname 传递设计 | zhangjf | | v1.3 | 2026-02-13 | 补充 HikariCP 连接池、支持异步场景的 UserContext 封装 | zhangjf | +| v1.4 | 2026-02-13 | 补充统一全局上下文 GlobalContext,统筹 tid/uid/uname 获取和异步传递 | zhangjf | ---