# 数据范围助手 **本文引用的文件** - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件为“数据范围助手”提供全面文档,聚焦于 DataScopeHelper 工具类与 DataVisibilityContext 上下文管理机制。内容涵盖: - 数据范围的设置、获取与清理操作 - 线程安全的数据可见性控制与跨方法调用时的数据范围传递 - 在业务逻辑中动态调整数据访问范围的实际使用模式 - 常见用法、最佳实践、异常处理与数据一致性保证 ## 项目结构 围绕数据范围能力的相关代码主要分布在基础模块与安全模块中: - 基础模块(crm-base)提供数据范围的核心工具与上下文管理 - 认证模块(crm-auth)提供拦截器与表级配置,将数据范围注入到查询条件中 - 测试用例覆盖集成与上下文行为验证 ```mermaid graph TB subgraph "基础模块 crm-base" A["DataScopeHelper
数据范围工具"] B["DataVisibilityContext
可见性上下文"] C["DataScopeLevel
数据范围级别"] D["DataOwnership
数据所有权注解"] E["LoginUser
登录用户信息"] F["SecurityUtils
安全工具"] G["DataScope 注解
声明式数据范围"] end subgraph "认证模块 crm-auth" H["DataScopeInterceptor
数据范围拦截器"] I["DataScopeTables
数据范围表配置"] end A --> B A --> C A --> E A --> F H --> I H --> A G --> H ``` 图表来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) 章节来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) ## 核心组件 - DataScopeHelper:提供数据范围的设置、获取、合并与清理等工具方法,支持按级别与表维度进行控制。 - DataVisibilityContext:基于线程局部变量的上下文容器,确保同一线程内数据范围的一致性与隔离性。 - DataScopeLevel:定义数据范围级别(如全部、本部门、本人等),用于限定可访问数据的边界。 - DataOwnership:注解,用于声明某实体或方法对特定数据的所有权,辅助范围推导。 - LoginUser:封装当前登录用户信息,作为数据范围计算的基础。 - SecurityUtils:安全相关工具,常用于从上下文中提取当前用户或权限信息。 - DataScope 注解:声明式标注接口或方法,配合拦截器自动注入数据范围过滤条件。 - DataScopeInterceptor:拦截请求,解析注解与表配置,将数据范围条件注入到 SQL 查询中。 - DataScopeTables:维护需要应用数据范围的表清单及映射规则。 章节来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) ## 架构总览 数据范围的整体流程如下: - 请求进入时,拦截器根据注解与表配置确定目标表与范围级别 - 通过工具类从当前用户与上下文推导出最终的数据范围集合 - 将范围条件注入到查询语句中,实现行级数据隔离 - 上下文在同一线程内保持可见性,跨方法调用无需显式传递 ```mermaid sequenceDiagram participant Client as "客户端" participant Interceptor as "数据范围拦截器" participant Helper as "数据范围助手" participant Context as "可见性上下文" participant DB as "数据库" Client->>Interceptor : "HTTP 请求" Interceptor->>Interceptor : "解析 @DataScope 与表配置" Interceptor->>Helper : "计算数据范围(用户+级别)" Helper->>Context : "读取/设置当前范围" Context-->>Helper : "返回范围集合" Helper-->>Interceptor : "返回范围条件" Interceptor->>DB : "执行带范围条件的查询" DB-->>Client : "返回受限结果集" ``` 图表来源 - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) ## 详细组件分析 ### DataScopeHelper:数据范围工具 职责与方法概览: - 设置数据范围:为当前线程设置指定级别与表维度的范围集合 - 获取数据范围:从上下文中读取当前有效的范围集合 - 合并数据范围:将多个范围集合合并去重,形成最终范围 - 清理数据范围:在方法结束后恢复或清空上下文中的范围,避免泄漏 - 范围推导:结合当前用户信息与级别枚举,生成初始范围 典型使用场景: - 在业务方法中临时扩大或缩小数据访问范围 - 在异步任务或子线程中继承父线程的范围上下文 - 在批量操作中统一设置范围,减少重复计算 ```mermaid flowchart TD Start(["进入方法"]) --> CheckCtx["检查上下文是否已有范围"] CheckCtx --> HasRange{"存在范围?"} HasRange --> |是| UseExisting["沿用现有范围"] HasRange --> |否| Compute["根据用户与级别计算范围"] Compute --> SetCtx["写入上下文"] UseExisting --> Execute["执行业务逻辑"] SetCtx --> Execute Execute --> Cleanup["清理/恢复上下文"] Cleanup --> End(["退出方法"]) ``` 图表来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) 章节来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) ### DataVisibilityContext:可见性上下文 设计要点: - 线程安全:基于 ThreadLocal 存储当前线程的数据范围集合,确保并发隔离 - 作用域管理:在进入方法前设置范围,退出时清理,防止上下文污染 - 继承与传播:支持在子线程创建时复制父线程范围,便于异步任务继承上下文 关键操作: - 设置范围:setScope(level, table, scopeSet) - 获取范围:getScope(level, table) - 清理范围:clearScope(level, table) 或 clearAll() ```mermaid classDiagram class DataVisibilityContext { +setScope(level, table, scopeSet) void +getScope(level, table) Set~String~ +clearScope(level, table) void +clearAll() void -threadLocalScope Map~String, Set~String~~ } ``` 图表来源 - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) 章节来源 - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) ### DataScopeLevel:数据范围级别 说明: - 定义不同粒度的数据访问级别,例如全部、本部门、本人等 - 与用户信息结合,生成具体的数据范围集合(如部门ID列表、用户ID列表) 章节来源 - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) ### DataOwnership:数据所有权注解 说明: - 标注实体或方法,表示其对某些数据的所有权关系 - 辅助范围推导,例如默认将所有者ID加入范围集合 章节来源 - [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) ### LoginUser 与 SecurityUtils:用户与安全工具 说明: - LoginUser 封装当前登录用户的关键属性(如用户ID、部门ID、角色等) - SecurityUtils 提供便捷方法从安全上下文获取当前用户或权限信息 章节来源 - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) ### DataScope 注解与 DataScopeInterceptor:声明式范围注入 说明: - DataScope 注解用于在接口或方法上声明数据范围级别与目标表 - DataScopeInterceptor 拦截请求,解析注解与表配置,将范围条件注入到查询中 ```mermaid sequenceDiagram participant Controller as "控制器" participant Interceptor as "数据范围拦截器" participant Tables as "表配置" participant Helper as "数据范围助手" participant Mapper as "数据访问层" Controller->>Interceptor : "调用被 @DataScope 标注的方法" Interceptor->>Tables : "读取目标表与级别映射" Interceptor->>Helper : "计算并获取范围集合" Helper-->>Interceptor : "返回范围条件" Interceptor->>Mapper : "执行带范围条件的查询" Mapper-->>Controller : "返回受限结果" ``` 图表来源 - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) 章节来源 - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) ## 依赖关系分析 - DataScopeHelper 依赖 DataVisibilityContext 进行范围存取,依赖 DataScopeLevel 与 LoginUser 进行范围推导 - DataScopeInterceptor 依赖 DataScopeTables 与 DataScopeHelper,负责将范围注入到查询 - 测试用例验证上下文行为与拦截器集成效果 ```mermaid graph LR Helper["DataScopeHelper"] --> Ctx["DataVisibilityContext"] Helper --> Level["DataScopeLevel"] Helper --> User["LoginUser"] Interceptor["DataScopeInterceptor"] --> Helper Interceptor --> Tables["DataScopeTables"] Test1["DataScopeIntegrationTest"] --> Interceptor Test2["DataVisibilityTest"] --> Ctx ``` 图表来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) 章节来源 - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - [DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java) - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) ## 性能考量 - 上下文存取开销低:ThreadLocal 的 get/set 操作为 O(1),适合高频调用 - 范围集合大小影响查询性能:范围过大可能导致 SQL IN 条件过长,建议分页或分批处理 - 缓存策略:对于稳定的范围集合(如部门成员列表)可考虑缓存,减少重复计算 - 清理时机:务必在方法结束或异常分支中清理上下文,避免内存泄漏与上下文污染 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 常见问题与定位思路: - 数据范围未生效 - 检查是否在请求入口正确设置范围 - 确认 @DataScope 注解与表配置是否正确 - 查看拦截器是否被启用且顺序正确 - 上下文泄漏导致范围污染 - 确保每个方法在 finally 块中清理范围 - 检查异步任务是否正确复制与清理上下文 - 范围过大导致查询缓慢 - 优化范围集合,增加过滤条件 - 使用分页或分批次查询 章节来源 - [DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - [DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) ## 结论 DataScopeHelper 与 DataVisibilityContext 共同构成了灵活、线程安全的数据范围控制体系。通过注解与拦截器的声明式注入,开发者可以在不侵入业务逻辑的前提下实现细粒度的数据隔离。遵循最佳实践与清理规范,可有效避免上下文污染与性能问题,保障数据一致性与系统稳定性。 [本节为总结,不直接分析具体文件] ## 附录 - 使用示例路径参考: - 集成测试:[DataScopeIntegrationTest.java](file://crm-auth/src/test/java/com/crm/auth/security/scope/DataScopeIntegrationTest.java) - 上下文行为测试:[DataVisibilityTest.java](file://crm-base/src/test/java/com/crm/base/security/DataVisibilityTest.java) - 关键类路径参考: - 数据范围工具:[DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - 可见性上下文:[DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - 范围级别:[DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - 数据所有权注解:[DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) - 登录用户信息:[LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - 安全工具:[SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - 声明式注解:[DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - 拦截器:[DataScopeInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeInterceptor.java) - 表配置:[DataScopeTables.java](file://crm-auth/src/main/java/com/crm/auth/security/DataScopeTables.java)