datai/docs/archive/decisions/adr/0032-error-handling-exception-mechanism.md

12 KiB
Raw Blame History

架构决策记录:错误处理和异常机制完善

背景

REQ-011-6 需求要求在 datai-salesforce-integration 模块实现完善的错误处理机制,包括自定义异常类、全局异常处理器、错误日志记录和错误信息封装。通过统一的错误处理机制,提高系统的健壮性,提供清晰的错误信息,提升用户体验。

面临的问题

  1. 异常类设计: 需要设计合理的自定义异常类,支持文件上传下载相关的异常场景
  2. 错误代码管理: 需要设计统一的错误代码枚举,集中管理所有错误代码
  3. 全局异常处理: 需要设计全局异常处理器,统一处理所有异常
  4. 错误响应封装: 需要设计统一的错误响应格式,提高 API 接口的一致性
  5. 错误日志记录: 需要设计合理的错误日志记录机制,记录所有错误信息
  6. 错误信息国际化: 需要设计错误信息国际化机制,支持多语言

约束条件

  1. 技术栈限制: 必须基于现有的 Spring Boot 3 技术栈
  2. 架构约束: 必须遵循 Authentication.canvas 中定义的架构和调用关系
  3. 模块约束: 必须在 datai-salesforce-integration 模块下实现
  4. 文档约束: 必须遵循 SSOT 方法论
  5. 代码规范: 必须遵循项目编码规范

决策

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: 不实现国际化

优点:

  • 实现简单,减少开发成本

缺点:

  • 不支持多语言,用户体验差
  • 不符合国际化最佳实践

评估: 不推荐使用

影响

系统架构影响

  1. 新增模块: 在 datai-salesforce-integration 模块下新增异常处理相关类
  2. 新增异常类: 新增 7 个自定义异常类
  3. 新增枚举类: 新增 FileErrorCode 枚举类
  4. 新增处理器: 新增 FileGlobalExceptionHandler 全局异常处理器
  5. 新增响应类: 新增 ErrorResponse 错误响应类
  6. 新增资源文件: 新增错误信息资源文件

开发流程影响

  1. 开发流程: 需要按照 SSOT 方法论进行开发,包括需求定义、方案决策、提示词资产化、执行会话、变更记录、闭环复盘
  2. 代码规范: 需要遵循项目编码规范,使用 Lombok 注解、Slf4j、Spring Boot 注解等
  3. 测试要求: 需要编写单元测试和集成测试,确保测试覆盖率 ≥ 90%

运维管理影响

  1. 监控要求: 需要监控错误日志,及时发现和解决问题
  2. 日志要求: 需要记录详细的错误日志,便于问题排查
  3. 国际化要求: 需要维护错误信息资源文件,确保多语言支持

风险

技术风险

  1. 异常类设计风险: 异常类设计可能不够完善
    • 缓解措施: 提前进行异常类设计评审,参考业界最佳实践
  2. 错误代码管理风险: 错误代码可能不够统一
    • 缓解措施: 使用枚举集中管理错误代码,提供静态方法进行转换
  3. 全局异常处理器风险: 全局异常处理器可能影响其他模块
    • 缓解措施: 使用 @RestControllerAdvice 注解,只处理文件上传下载相关的异常
  4. 错误日志记录风险: 错误日志记录可能不够详细
    • 缓解措施: 记录详细的错误信息,包括异常类型、错误信息、错误代码、请求参数、请求路径、时间戳等

业务风险

  1. 兼容性风险: 前端可能不兼容新的错误响应格式
    • 缓解措施: 提供详细的 API 文档,提供前端集成指南
  2. 国际化风险: 国际化实现可能不够完善
    • 缓解措施: 提前进行国际化测试,确保多语言支持

实施风险

  1. 开发风险: 开发过程中可能遇到技术难题
    • 缓解措施: 提前进行技术调研,参考官方文档和示例代码
  2. 测试风险: 测试过程中可能发现性能问题
    • 缓解措施: 提前进行性能测试,优化代码性能

回滚策略

回滚条件

  1. 功能不满足需求: 如果实现的功能不满足需求,可以进行回滚
  2. 性能不达标: 如果性能不达标,可以进行回滚或优化
  3. 严重Bug: 如果发现严重Bug可以进行回滚或修复

回滚步骤

  1. 代码回滚: 使用 Git 回滚代码到上一个稳定版本
  2. 配置回滚: 如果有配置变更,需要回滚配置
  3. 通知用户: 通知用户回滚的原因和影响

回滚后调整

  1. 问题分析: 分析回滚的原因,找出问题所在
  2. 方案优化: 优化方案,解决存在的问题
  3. 重新实施: 重新实施优化后的方案

验收标准

功能验收标准

  1. 异常处理: 能够正确处理所有异常,提供清晰的错误信息
  2. 错误响应: 能够返回统一的错误响应格式
  3. 错误日志: 能够记录详细的错误日志,便于问题排查
  4. 国际化: 能够根据请求头返回对应语言的错误信息
  5. 参数验证: 能够正确处理参数验证异常,提供详细的错误信息

性能验收标准

  1. 异常处理性能: 异常处理性能良好,不影响系统响应
  2. 日志记录性能: 日志记录性能良好,不影响系统响应

代码质量验收标准

  1. 代码规范: 代码符合项目编码规范,有清晰的注释
  2. 单一职责: 遵循单一职责原则和开闭原则
  3. 测试覆盖: 测试覆盖率 ≥ 90%

国际化验收标准

  1. 多语言支持: 支持中文和英文
  2. 语言切换: 能够根据请求头正确切换语言
  3. 错误信息: 错误信息准确、清晰

视觉锚点

Visual Reference

引用 Canvas 的具体节点或快照:

Status

  • Draft
  • Accepted
  • Superceded

参考资料

列出与该决策相关的参考资料,包括文档、文章或其他资源。