12 KiB
12 KiB
架构决策记录:错误处理和异常机制完善
背景
REQ-011-6 需求要求在 datai-salesforce-integration 模块实现完善的错误处理机制,包括自定义异常类、全局异常处理器、错误日志记录和错误信息封装。通过统一的错误处理机制,提高系统的健壮性,提供清晰的错误信息,提升用户体验。
面临的问题
- 异常类设计: 需要设计合理的自定义异常类,支持文件上传下载相关的异常场景
- 错误代码管理: 需要设计统一的错误代码枚举,集中管理所有错误代码
- 全局异常处理: 需要设计全局异常处理器,统一处理所有异常
- 错误响应封装: 需要设计统一的错误响应格式,提高 API 接口的一致性
- 错误日志记录: 需要设计合理的错误日志记录机制,记录所有错误信息
- 错误信息国际化: 需要设计错误信息国际化机制,支持多语言
约束条件
- 技术栈限制: 必须基于现有的 Spring Boot 3 技术栈
- 架构约束: 必须遵循 Authentication.canvas 中定义的架构和调用关系
- 模块约束: 必须在 datai-salesforce-integration 模块下实现
- 文档约束: 必须遵循 SSOT 方法论
- 代码规范: 必须遵循项目编码规范
决策
1. 自定义异常类设计
决策: 定义文件上传下载相关的自定义异常类,所有异常类继承自 RuntimeException
理由:
- RuntimeException 是 Java 标准的非受检异常,符合 Spring Boot 异常处理最佳实践
- 继承自 RuntimeException 可以避免强制异常处理,提高代码可读性
- 提供异常链支持(cause),便于异常追踪
- 提供错误代码和错误消息,便于错误处理和日志记录
实现方案:
- 定义 FileUploadException 异常类,包含 errorCode 字段
- 定义 FileDownloadException 异常类,包含 errorCode 字段
- 定义 FileSizeExceededException 异常类,包含 actualSize 和 maxSize 字段
- 定义 FileTypeNotSupportedException 异常类,包含 actualType 和 supportedTypes 字段
- 定义 FileObjectNotFoundException 异常类,包含 objectId 和 objectType 字段
- 定义 OrgConfigNotFoundException 异常类,包含 orgConfigId 字段
- 定义 FileValidationException 异常类,包含 validationType 字段
- 所有异常类继承自 RuntimeException
- 使用 Lombok 注解(@Data、@AllArgsConstructor、@NoArgsConstructor)简化代码
2. 错误代码枚举设计
决策: 定义 FileErrorCode 枚举,统一管理所有错误代码
理由:
- 使用枚举可以集中管理错误代码,避免魔法值
- 提供错误代码的描述信息,便于错误处理和日志记录
- 提供 HTTP 状态码,便于返回正确的 HTTP 状态码
- 提供静态方法进行转换,提高代码可读性
实现方案:
- 定义 FileErrorCode 枚举,包含所有文件上传下载相关的错误代码
- 每个枚举值包含 code、description、httpStatus 字段
- 提供 getByCode() 静态方法,根据错误代码获取枚举值
- 提供 getByHttpStatus() 静态方法,根据 HTTP 状态码获取枚举值
- 使用 @Getter 注解简化代码
3. 全局异常处理器设计
决策: 实现 FileGlobalExceptionHandler 类,使用 @RestControllerAdvice 注解
理由:
- @RestControllerAdvice 是 Spring Boot 3 推荐的全局异常处理器注解
- 可以统一处理所有异常,避免重复的异常处理代码
- 可以返回统一的错误响应格式,提高 API 接口的一致性
- 可以记录错误日志,便于问题排查
实现方案:
- 定义 FileGlobalExceptionHandler 类,使用 @RestControllerAdvice 注解
- 使用 @Slf4j 注解记录日志
- 使用 @ExceptionHandler 注解处理各种异常:
- 处理 FileUploadException 异常
- 处理 FileDownloadException 异常
- 处理 FileSizeExceededException 异常
- 处理 FileTypeNotSupportedException 异常
- 处理 FileObjectNotFoundException 异常
- 处理 OrgConfigNotFoundException 异常
- 处理 FileValidationException 异常
- 处理 MethodArgumentNotValidException 异常(参数验证失败)
- 处理 HttpRequestMethodNotSupportedException 异常(HTTP 方法不支持)
- 处理 HttpMediaTypeNotSupportedException 异常(Content-Type 不支持)
- 处理 MaxUploadSizeExceededException 异常(文件大小超限)
- 处理其他未捕获的异常
- 返回统一的错误响应格式(ErrorResponse)
- 记录详细的错误日志
4. 错误响应封装设计
决策: 定义 ErrorResponse 响应类,封装错误信息
理由:
- 统一的错误响应格式可以提高 API 接口的一致性
- 便于前端处理错误响应
- 便于错误处理和日志记录
- 符合业界最佳实践
实现方案:
- 定义 ErrorResponse 响应类,包含以下字段:
- code:错误代码
- message:错误消息
- details:错误详情(可选)
- timestamp:时间戳
- path:请求路径(可选)
- 使用 Lombok 注解(@Data、@Builder、@AllArgsConstructor、@NoArgsConstructor)简化代码
- 提供静态工厂方法,便于构建错误响应
5. 错误日志记录设计
决策: 在全局异常处理器中记录错误日志,使用 Slf4j
理由:
- Slf4j 是 Java 标准的日志框架,符合 Spring Boot 最佳实践
- 可以记录详细的错误信息,便于问题排查
- 可以使用不同的日志级别,区分错误严重程度
- 可以配置日志格式和输出位置
实现方案:
- 在全局异常处理器中使用 @Slf4j 记录日志
- 记录异常类型
- 记录错误信息
- 记录错误代码
- 记录请求参数
- 记录请求路径
- 记录时间戳
- 记录异常堆栈(可选)
- 使用不同的日志级别:
- ERROR:记录业务异常
- WARN:记录参数验证异常
- ERROR:记录未捕获的异常
6. 错误信息国际化设计
决策: 实现错误信息国际化,使用 Spring 的 MessageSource
理由:
- 支持多语言可以提高用户体验
- Spring 的 MessageSource 是标准的国际化解决方案
- 可以根据请求头 Accept-Language 返回对应语言的错误信息
- 符合业界最佳实践
实现方案:
- 定义错误信息资源文件:
- messages.properties(默认,英文)
- messages_zh_CN.properties(中文)
- 在资源文件中定义所有错误信息
- 在全局异常处理器中使用 MessageSource 获取错误信息
- 根据请求头 Accept-Language 返回对应语言的错误信息
- 使用 LocaleContextHolder 获取当前 Locale
备选方案
方案 1: 使用受检异常
优点:
- 强制调用者处理异常,提高代码健壮性
- 编译时检查,避免遗漏异常处理
缺点:
- 增加代码复杂度,需要大量 try-catch 块
- 不符合 Spring Boot 异常处理最佳实践
- 降低代码可读性
评估: 不推荐使用
方案 2: 不使用全局异常处理器
优点:
- 灵活性高,每个方法可以自定义异常处理
缺点:
- 代码冗余,重复的异常处理代码
- 错误响应格式不统一
- 不便于错误日志记录
评估: 不推荐使用
方案 3: 不实现国际化
优点:
- 实现简单,减少开发成本
缺点:
- 不支持多语言,用户体验差
- 不符合国际化最佳实践
评估: 不推荐使用
影响
系统架构影响
- 新增模块: 在 datai-salesforce-integration 模块下新增异常处理相关类
- 新增异常类: 新增 7 个自定义异常类
- 新增枚举类: 新增 FileErrorCode 枚举类
- 新增处理器: 新增 FileGlobalExceptionHandler 全局异常处理器
- 新增响应类: 新增 ErrorResponse 错误响应类
- 新增资源文件: 新增错误信息资源文件
开发流程影响
- 开发流程: 需要按照 SSOT 方法论进行开发,包括需求定义、方案决策、提示词资产化、执行会话、变更记录、闭环复盘
- 代码规范: 需要遵循项目编码规范,使用 Lombok 注解、Slf4j、Spring Boot 注解等
- 测试要求: 需要编写单元测试和集成测试,确保测试覆盖率 ≥ 90%
运维管理影响
- 监控要求: 需要监控错误日志,及时发现和解决问题
- 日志要求: 需要记录详细的错误日志,便于问题排查
- 国际化要求: 需要维护错误信息资源文件,确保多语言支持
风险
技术风险
- 异常类设计风险: 异常类设计可能不够完善
- 缓解措施: 提前进行异常类设计评审,参考业界最佳实践
- 错误代码管理风险: 错误代码可能不够统一
- 缓解措施: 使用枚举集中管理错误代码,提供静态方法进行转换
- 全局异常处理器风险: 全局异常处理器可能影响其他模块
- 缓解措施: 使用 @RestControllerAdvice 注解,只处理文件上传下载相关的异常
- 错误日志记录风险: 错误日志记录可能不够详细
- 缓解措施: 记录详细的错误信息,包括异常类型、错误信息、错误代码、请求参数、请求路径、时间戳等
业务风险
- 兼容性风险: 前端可能不兼容新的错误响应格式
- 缓解措施: 提供详细的 API 文档,提供前端集成指南
- 国际化风险: 国际化实现可能不够完善
- 缓解措施: 提前进行国际化测试,确保多语言支持
实施风险
- 开发风险: 开发过程中可能遇到技术难题
- 缓解措施: 提前进行技术调研,参考官方文档和示例代码
- 测试风险: 测试过程中可能发现性能问题
- 缓解措施: 提前进行性能测试,优化代码性能
回滚策略
回滚条件
- 功能不满足需求: 如果实现的功能不满足需求,可以进行回滚
- 性能不达标: 如果性能不达标,可以进行回滚或优化
- 严重Bug: 如果发现严重Bug,可以进行回滚或修复
回滚步骤
- 代码回滚: 使用 Git 回滚代码到上一个稳定版本
- 配置回滚: 如果有配置变更,需要回滚配置
- 通知用户: 通知用户回滚的原因和影响
回滚后调整
- 问题分析: 分析回滚的原因,找出问题所在
- 方案优化: 优化方案,解决存在的问题
- 重新实施: 重新实施优化后的方案
验收标准
功能验收标准
- 异常处理: 能够正确处理所有异常,提供清晰的错误信息
- 错误响应: 能够返回统一的错误响应格式
- 错误日志: 能够记录详细的错误日志,便于问题排查
- 国际化: 能够根据请求头返回对应语言的错误信息
- 参数验证: 能够正确处理参数验证异常,提供详细的错误信息
性能验收标准
- 异常处理性能: 异常处理性能良好,不影响系统响应
- 日志记录性能: 日志记录性能良好,不影响系统响应
代码质量验收标准
- 代码规范: 代码符合项目编码规范,有清晰的注释
- 单一职责: 遵循单一职责原则和开闭原则
- 测试覆盖: 测试覆盖率 ≥ 90%
国际化验收标准
- 多语言支持: 支持中文和英文
- 语言切换: 能够根据请求头正确切换语言
- 错误信息: 错误信息准确、清晰
视觉锚点
Visual Reference
引用 Canvas 的具体节点或快照:
- Authentication.canvas - 项目架构视觉化展示
- 具体节点: 通用异常 - 定义Salesforce相关的异常类
- 具体节点: 集成核心 - 提供与Salesforce的各种连接方式
Status
- Draft
- Accepted
- Superceded
参考资料
列出与该决策相关的参考资料,包括文档、文章或其他资源。
- REQ-011.md - Salesforce文件上传下载功能
- REQ-011-1.md - 基础设施和枚举定义
- REQ-011-6.md - 错误处理和异常机制完善
- 0027-file-infrastructure-enums.md - 文件上传下载基础设施架构决策
- Spring Boot 异常处理文档 - Spring Boot 异常处理官方文档
- Spring Boot 国际化文档 - Spring Boot 国际化官方文档