如果让你设计一套项目里的异常处理体系,业务异常、系统异常和第三方异常会怎么划分?
我的判断
异常体系的目标不是把类分得漂亮,而是让调用方知道能否重试、用户看到什么、事务是否回滚、日志由谁记录。
我会按处理方式分,而不是按技术名词分。业务异常 是库存不足、优惠券不可用这类可预期结果,带稳定错误码,通常不打印堆栈;系统异常 是空指针、数据库不可用,统一转成内部错误并在边界记录完整现场;第三方异常 还要区分超时、限流、明确失败和结果未知,因为只有一部分适合重试。
落地时,领域层抛带业务语义的异常,接口层统一映射 HTTP/RPC 响应。日志只在“已经决定如何处理”的边界记一次,里面带 traceId、订单号、下游、耗时和原始错误码,避免每层 catch 一次、同一故障刷十遍日志。
重试也不会写成通用注解无脑执行:
- 参数错误和明确拒绝不重试;
- 超时且操作幂等时,指数退避并限制次数;
- 支付结果未知时先查单,不能直接再次扣款。
事务边界会显式约定哪些异常回滚。对外返回不暴露 SQL、文件路径等内部信息,但告警和日志必须保留原始 cause。
思路拆解问题分析
设计异常体系时,我会从四个问题反推:用户能否修正、调用方能否重试、当前事务是否还能提交、值班人员需要什么证据。 同一个“调用失败”,如果是余额不足、网络超时和第三方受理后无响应,处理动作完全不同,不能只用一个 RuntimeException。