You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
16 KiB
385 lines
16 KiB
|
1 month ago
|
# 工具类库
|
||
|
|
|
||
|
|
<cite>
|
||
|
|
**本文引用的文件**
|
||
|
|
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
|
||
|
|
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
|
||
|
|
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
|
||
|
|
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
|
||
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
||
|
|
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
|
||
|
|
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
|
||
|
|
</cite>
|
||
|
|
|
||
|
|
## 目录
|
||
|
|
1. [简介](#简介)
|
||
|
|
2. [项目结构](#项目结构)
|
||
|
|
3. [核心组件](#核心组件)
|
||
|
|
4. [架构总览](#架构总览)
|
||
|
|
5. [详细组件分析](#详细组件分析)
|
||
|
|
6. [依赖关系分析](#依赖关系分析)
|
||
|
|
7. [性能考虑](#性能考虑)
|
||
|
|
8. [故障排查指南](#故障排查指南)
|
||
|
|
9. [结论](#结论)
|
||
|
|
10. [附录](#附录)
|
||
|
|
|
||
|
|
## 简介
|
||
|
|
本仓库的 crm-base 模块提供了一套通用工具类,覆盖分页转换、对象拷贝、枚举处理、Excel 导入导出、树形结构构建、断言校验与 Servlet 辅助等常见场景。本文面向开发者与使用者,系统化梳理各工具类的职责、API 能力、使用方式与优化建议,帮助在业务代码中高效复用并避免常见问题。
|
||
|
|
|
||
|
|
## 项目结构
|
||
|
|
工具类均位于 crm-base 模块的 utils 包下,按功能划分清晰:
|
||
|
|
- PageConverter:分页数据转换器
|
||
|
|
- BeanCopyUtils:对象属性拷贝工具
|
||
|
|
- EnumUtils:枚举查询与映射工具
|
||
|
|
- ExcelUtil:Excel 读写与模板导出工具
|
||
|
|
- TreeUtils:树形结构构建与遍历工具
|
||
|
|
- AssertUtils:参数与状态断言工具
|
||
|
|
- ServletUtils:请求上下文与参数解析工具
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
subgraph "crm-base/utils"
|
||
|
|
A["PageConverter"]
|
||
|
|
B["BeanCopyUtils"]
|
||
|
|
C["EnumUtils"]
|
||
|
|
D["ExcelUtil"]
|
||
|
|
E["TreeUtils"]
|
||
|
|
F["AssertUtils"]
|
||
|
|
G["ServletUtils"]
|
||
|
|
end
|
||
|
|
A --> |使用| H["PageResult"]
|
||
|
|
B --> |反射| I["Java 反射 API"]
|
||
|
|
C --> |枚举| J["HasValueEnum / StatusEnum"]
|
||
|
|
D --> |POI/EasyExcel| K["Excel 引擎"]
|
||
|
|
E --> |集合操作| L["List/Set"]
|
||
|
|
F --> |异常| M["BusinessErrorException"]
|
||
|
|
G --> |Spring MVC| N["HttpServletRequest/Response"]
|
||
|
|
```
|
||
|
|
|
||
|
|
[本图为概念性结构示意,不直接对应具体源码文件]
|
||
|
|
|
||
|
|
## 核心组件
|
||
|
|
- PageConverter:将数据库分页结果转换为统一的分页响应 DTO,支持字段映射与类型安全转换。
|
||
|
|
- BeanCopyUtils:基于反射的对象拷贝,支持忽略空值、指定字段拷贝与自定义映射策略。
|
||
|
|
- EnumUtils:根据编码或描述快速查找枚举实例,支持默认值与批量转换。
|
||
|
|
- ExcelUtil:封装 Excel 读取与导出,支持表头注解、数据校验与流式写入。
|
||
|
|
- TreeUtils:将扁平列表转换为树形结构,支持多级节点、排序与过滤。
|
||
|
|
- AssertUtils:集中化的断言方法,失败时抛出业务异常,便于统一错误处理。
|
||
|
|
- ServletUtils:从请求中提取参数、Header、IP、用户信息等常用信息。
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
|
||
|
|
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
|
||
|
|
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
|
||
|
|
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
|
||
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
||
|
|
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
|
||
|
|
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
|
||
|
|
|
||
|
|
## 架构总览
|
||
|
|
工具类之间保持低耦合,主要依赖 Spring 基础能力与 Java 标准库;Excel 工具依赖第三方 Excel 引擎;分页转换依赖统一分页结果模型。整体设计遵循“单一职责 + 静态工具方法”模式,便于无状态调用与测试。
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph TB
|
||
|
|
Utils["工具类集合"]
|
||
|
|
PC["PageConverter"]
|
||
|
|
BC["BeanCopyUtils"]
|
||
|
|
EU["EnumUtils"]
|
||
|
|
EX["ExcelUtil"]
|
||
|
|
TU["TreeUtils"]
|
||
|
|
AU["AssertUtils"]
|
||
|
|
SU["ServletUtils"]
|
||
|
|
PR["PageResult"]
|
||
|
|
RE["反射/集合/IO"]
|
||
|
|
POI["Excel 引擎"]
|
||
|
|
SPRING["Spring MVC"]
|
||
|
|
Utils --> PC
|
||
|
|
Utils --> BC
|
||
|
|
Utils --> EU
|
||
|
|
Utils --> EX
|
||
|
|
Utils --> TU
|
||
|
|
Utils --> AU
|
||
|
|
Utils --> SU
|
||
|
|
PC --> PR
|
||
|
|
BC --> RE
|
||
|
|
EU --> RE
|
||
|
|
EX --> POI
|
||
|
|
TU --> RE
|
||
|
|
AU --> RE
|
||
|
|
SU --> SPRING
|
||
|
|
```
|
||
|
|
|
||
|
|
[本图为概念性依赖示意,不直接对应具体源码文件]
|
||
|
|
|
||
|
|
## 详细组件分析
|
||
|
|
|
||
|
|
### PageConverter 分页转换工具
|
||
|
|
- 职责:将数据库分页对象(如 MyBatis-Plus 的 IPage)转换为统一的分页响应 DTO(PageResult),支持字段映射与类型转换。
|
||
|
|
- 关键能力:
|
||
|
|
- 分页数据转换:记录数、页码、每页大小、数据列表的映射
|
||
|
|
- 字段级映射:支持按名称或自定义映射规则进行字段转换
|
||
|
|
- 类型安全:对数值、日期、布尔等类型的自动转换与校验
|
||
|
|
- 典型用法:
|
||
|
|
- 服务层返回 IPage<Entity>,通过 PageConverter 转为 PageResult<DTO>
|
||
|
|
- 复杂对象嵌套映射时,结合 BeanCopyUtils 完成子对象转换
|
||
|
|
- 性能要点:
|
||
|
|
- 避免在循环内重复创建映射器
|
||
|
|
- 大数据量分页时优先做服务端过滤与投影,减少内存占用
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["进入转换"]) --> CheckInput["检查输入是否为空"]
|
||
|
|
CheckInput --> |为空| ReturnEmpty["返回空分页结果"]
|
||
|
|
CheckInput --> |非空| MapMeta["映射元数据<br/>total/current/size"]
|
||
|
|
MapMeta --> MapData["映射数据列表"]
|
||
|
|
MapData --> TypeConvert["类型转换与校验"]
|
||
|
|
TypeConvert --> BuildResult["构建 PageResult"]
|
||
|
|
BuildResult --> End(["返回结果"])
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
|
||
|
|
|
||
|
|
### BeanCopyUtils 对象拷贝工具
|
||
|
|
- 职责:基于反射实现对象属性拷贝,支持忽略空值、指定字段拷贝与自定义映射策略。
|
||
|
|
- 关键能力:
|
||
|
|
- 全量拷贝:同名同类型字段自动复制
|
||
|
|
- 选择性拷贝:白名单/黑名单字段控制
|
||
|
|
- 空值策略:忽略 null 或覆盖目标值
|
||
|
|
- 自定义映射:字段名不一致时的映射规则
|
||
|
|
- 典型用法:
|
||
|
|
- Entity 到 DTO 的单向拷贝
|
||
|
|
- DTO 到 VO 的展示层转换
|
||
|
|
- 合并多个源对象的属性到目标对象
|
||
|
|
- 性能要点:
|
||
|
|
- 高频场景可缓存映射策略
|
||
|
|
- 避免深层嵌套对象的过度拷贝
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class BeanCopyUtils {
|
||
|
|
+copy(source, target) void
|
||
|
|
+copyIgnoreNull(source, target) void
|
||
|
|
+copyWithMapping(source, target, mapping) void
|
||
|
|
-resolveField(sourceType, targetType, fieldName) Field
|
||
|
|
-applyConversion(value, targetType) Object
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
|
||
|
|
|
||
|
|
### EnumUtils 枚举工具
|
||
|
|
- 职责:提供枚举的查询、转换与校验能力,简化业务中对枚举的使用。
|
||
|
|
- 关键能力:
|
||
|
|
- 按编码获取枚举实例
|
||
|
|
- 按描述获取枚举实例
|
||
|
|
- 批量转换字符串为枚举列表
|
||
|
|
- 默认值与非法值处理
|
||
|
|
- 典型用法:
|
||
|
|
- 前端传入的状态码转后端枚举
|
||
|
|
- 下拉选项枚举值的统一获取
|
||
|
|
- 性能要点:
|
||
|
|
- 枚举查找应基于常量时间复杂度(如 Map 缓存)
|
||
|
|
- 批量转换时避免重复解析
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["枚举查询入口"]) --> ChooseMode{"选择查询模式"}
|
||
|
|
ChooseMode --> |按编码| FindByCode["根据编码查找"]
|
||
|
|
ChooseMode --> |按描述| FindByDesc["根据描述查找"]
|
||
|
|
FindByCode --> Valid{"是否找到?"}
|
||
|
|
FindByDesc --> Valid
|
||
|
|
Valid --> |是| ReturnEnum["返回枚举实例"]
|
||
|
|
Valid --> |否| HandleDefault["处理默认值或抛错"]
|
||
|
|
HandleDefault --> End(["结束"])
|
||
|
|
ReturnEnum --> End
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
|
||
|
|
|
||
|
|
### ExcelUtil Excel 文件处理工具
|
||
|
|
- 职责:封装 Excel 文件的读取与导出,支持表头注解、数据校验与流式写入。
|
||
|
|
- 关键能力:
|
||
|
|
- 导入:解析 Excel 为对象列表,支持必填校验、格式校验
|
||
|
|
- 导出:将对象列表导出为 Excel,支持多 Sheet、样式配置
|
||
|
|
- 模板导出:基于模板填充数据,适合报表场景
|
||
|
|
- 典型用法:
|
||
|
|
- 批量导入用户数据,返回错误行与提示信息
|
||
|
|
- 导出订单明细为 Excel 供下载
|
||
|
|
- 性能要点:
|
||
|
|
- 大文件导入使用流式解析,避免 OOM
|
||
|
|
- 导出时使用 SXSSFWorkbook 或 EasyExcel 的流式 API
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
sequenceDiagram
|
||
|
|
participant Client as "客户端"
|
||
|
|
participant Controller as "控制器"
|
||
|
|
participant ExcelUtil as "ExcelUtil"
|
||
|
|
participant Validator as "数据校验器"
|
||
|
|
participant Service as "业务服务"
|
||
|
|
Client->>Controller : 上传 Excel 文件
|
||
|
|
Controller->>ExcelUtil : 解析文件为对象列表
|
||
|
|
ExcelUtil-->>Controller : List<Object>
|
||
|
|
Controller->>Validator : 校验数据合法性
|
||
|
|
Validator-->>Controller : 校验结果
|
||
|
|
Controller->>Service : 批量保存有效数据
|
||
|
|
Service-->>Controller : 保存结果
|
||
|
|
Controller-->>Client : 返回导入结果
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
|
||
|
|
|
||
|
|
### TreeUtils 树形结构处理工具
|
||
|
|
- 职责:将扁平列表转换为树形结构,支持多级节点、排序与过滤。
|
||
|
|
- 关键能力:
|
||
|
|
- 层级构建:根据父 ID 与子 ID 关系构建树
|
||
|
|
- 排序策略:支持按权重、时间等字段排序
|
||
|
|
- 过滤条件:按状态、权限等过滤节点
|
||
|
|
- 典型用法:
|
||
|
|
- 菜单树、部门树的构建
|
||
|
|
- 分类树、标签树的生成
|
||
|
|
- 性能要点:
|
||
|
|
- 使用 Map 缓存父子关系,避免 O(n^2) 复杂度
|
||
|
|
- 大数据集时先过滤再构建,减少内存占用
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["开始构建"]) --> LoadList["加载扁平列表"]
|
||
|
|
LoadList --> GroupByParent["按父 ID 分组"]
|
||
|
|
GroupByParent --> BuildRoot["构建根节点"]
|
||
|
|
BuildRoot --> AttachChildren["递归挂载子节点"]
|
||
|
|
AttachChildren --> ApplySort["应用排序策略"]
|
||
|
|
ApplySort --> ApplyFilter["应用过滤条件"]
|
||
|
|
ApplyFilter --> ReturnTree["返回树形结构"]
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
||
|
|
|
||
|
|
### AssertUtils 断言工具
|
||
|
|
- 职责:集中化的断言方法,用于参数校验与前置条件检查。
|
||
|
|
- 关键能力:
|
||
|
|
- 非空断言:对象、集合、字符串的非空检查
|
||
|
|
- 条件断言:满足条件则继续,否则抛出业务异常
|
||
|
|
- 自定义消息:支持动态错误消息
|
||
|
|
- 典型用法:
|
||
|
|
- 接口入参校验
|
||
|
|
- 业务逻辑前置条件检查
|
||
|
|
- 性能要点:
|
||
|
|
- 断言失败即抛异常,避免不必要的后续计算
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
flowchart TD
|
||
|
|
Start(["断言入口"]) --> CheckCondition{"条件成立?"}
|
||
|
|
CheckCondition --> |是| Continue["继续执行"]
|
||
|
|
CheckCondition --> |否| ThrowError["抛出业务异常"]
|
||
|
|
ThrowError --> End(["结束"])
|
||
|
|
Continue --> End
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
|
||
|
|
|
||
|
|
### ServletUtils Servlet 工具
|
||
|
|
- 职责:封装 HttpServletRequest/Response 的常用操作,简化 Web 层开发。
|
||
|
|
- 关键能力:
|
||
|
|
- 参数提取:表单参数、查询参数、路径参数
|
||
|
|
- Header 读取:Authorization、Content-Type 等
|
||
|
|
- 用户信息:从 Token 或 Session 获取当前用户
|
||
|
|
- IP 地址:获取真实客户端 IP
|
||
|
|
- 典型用法:
|
||
|
|
- 登录接口中解析 Token 获取用户信息
|
||
|
|
- 审计日志中记录请求来源 IP
|
||
|
|
- 性能要点:
|
||
|
|
- 避免频繁创建 Request/Response 包装对象
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
classDiagram
|
||
|
|
class ServletUtils {
|
||
|
|
+getParam(request, name) String
|
||
|
|
+getHeader(request, name) String
|
||
|
|
+getCurrentUser() LoginUser
|
||
|
|
+getClientIp(request) String
|
||
|
|
-parseToken(token) Claims
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
|
||
|
|
|
||
|
|
## 依赖关系分析
|
||
|
|
工具类之间的依赖关系如下:
|
||
|
|
- PageConverter 依赖统一分页结果模型
|
||
|
|
- BeanCopyUtils 依赖 Java 反射 API
|
||
|
|
- EnumUtils 依赖枚举定义与可能的缓存
|
||
|
|
- ExcelUtil 依赖第三方 Excel 引擎(如 Apache POI 或 EasyExcel)
|
||
|
|
- TreeUtils 依赖集合操作与比较器
|
||
|
|
- AssertUtils 依赖业务异常类
|
||
|
|
- ServletUtils 依赖 Spring MVC 的请求响应对象
|
||
|
|
|
||
|
|
```mermaid
|
||
|
|
graph LR
|
||
|
|
PC["PageConverter"] --> PR["PageResult"]
|
||
|
|
BC["BeanCopyUtils"] --> REF["反射 API"]
|
||
|
|
EU["EnumUtils"] --> ENUM["枚举定义"]
|
||
|
|
EX["ExcelUtil"] --> POI["Excel 引擎"]
|
||
|
|
TU["TreeUtils"] --> COL["集合操作"]
|
||
|
|
AU["AssertUtils"] --> EXC["业务异常"]
|
||
|
|
SU["ServletUtils"] --> MVC["Spring MVC"]
|
||
|
|
```
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
|
||
|
|
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
|
||
|
|
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
|
||
|
|
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
|
||
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
||
|
|
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
|
||
|
|
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
|
||
|
|
|
||
|
|
## 性能考虑
|
||
|
|
- 分页转换:避免在转换过程中进行大量计算,优先在服务端完成过滤与投影
|
||
|
|
- 对象拷贝:高频场景缓存映射策略,减少反射开销
|
||
|
|
- 枚举处理:使用 Map 缓存枚举实例,避免重复查找
|
||
|
|
- Excel 处理:大文件使用流式 API,避免内存溢出
|
||
|
|
- 树形构建:使用 Map 缓存父子关系,降低时间复杂度
|
||
|
|
- 断言校验:尽早失败,避免不必要的后续计算
|
||
|
|
- Servlet 工具:避免重复解析相同信息,可结合 ThreadLocal 缓存
|
||
|
|
|
||
|
|
## 故障排查指南
|
||
|
|
- 分页转换失败:检查输入对象是否为空,字段映射是否正确
|
||
|
|
- 对象拷贝异常:确认字段类型是否兼容,是否存在访问权限问题
|
||
|
|
- 枚举查找失败:检查枚举编码或描述是否匹配,是否提供了默认值
|
||
|
|
- Excel 导入失败:查看错误行提示,检查数据格式与必填项
|
||
|
|
- 树形结构异常:确认父子 ID 关系是否正确,是否存在循环引用
|
||
|
|
- 断言失败:检查入参是否符合预期,调整断言条件
|
||
|
|
- Servlet 工具异常:检查请求上下文是否可用,Token 是否有效
|
||
|
|
|
||
|
|
**章节来源**
|
||
|
|
- [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java)
|
||
|
|
- [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java)
|
||
|
|
- [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java)
|
||
|
|
- [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java)
|
||
|
|
- [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java)
|
||
|
|
- [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java)
|
||
|
|
- [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java)
|
||
|
|
|
||
|
|
## 结论
|
||
|
|
本工具类库提供了企业级应用中常见的通用能力,覆盖了数据处理、对象转换、文件处理、结构构建与校验等核心场景。通过统一的 API 设计与良好的性能优化,显著提升了开发效率与代码质量。建议在各模块中优先复用这些工具类,保持一致性与可维护性。
|
||
|
|
|
||
|
|
## 附录
|
||
|
|
- 最佳实践:
|
||
|
|
- 在 Service 层使用 PageConverter 进行分页转换
|
||
|
|
- 在 Controller 层使用 AssertUtils 进行参数校验
|
||
|
|
- 在数据层使用 BeanCopyUtils 进行对象转换
|
||
|
|
- 在文件处理中使用 ExcelUtil 的流式 API
|
||
|
|
- 在权限控制中使用 TreeUtils 构建菜单树
|
||
|
|
- 在 Web 层使用 ServletUtils 获取请求信息
|
||
|
|
- 常见问题:
|
||
|
|
- 避免在循环中进行反射操作
|
||
|
|
- 大文件处理务必使用流式 API
|
||
|
|
- 枚举查找应提供默认值或明确错误处理
|
||
|
|
- 树形结构构建前进行数据清洗
|