1. 异常处理的分层原则中哪一层捕获、哪一层转译、哪一层兜底?"吞异常"和"异常当流程控制"两类反模式的危害?
异常处理的分层原则:哪一层捕获、哪一层转译、哪一层兜底?"吞异常"和"异常当流程控制"两类反模式的危害?
- 异常处理的分层(捕获/转译/兜底)
- "吞异常"反模式
- "异常当流程控制"反模式
(1)分层原则:a) 业务层"捕获"——处理可恢复的业务异常,转成业务结果;b) 边界层"转译"——把底层异常(DB、IO)转成领域/API 异常,不泄露实现细节;c) 框架层"兜底"——全局异常处理(@ControllerAdvice)捕获未处理的异常,统一转错误响应与日志。核心是"面向异常类型的处理在各层各自责任"。 (2)"吞异常"危害:catch (Exception e) {} 静默吞掉异常,丢失错误信息,导致"看起来成功实则失败",难排查、难监控。应记录或传播,而非吞掉。 (3)"异常当流程控制"危害:用异常处理正常业务分支(如用 NumberFormatException 判断是否是数字),异常创建昂贵、语义混乱、控制流难读。应改用返回值/条件判断。 (4)分层落地:每层只捕获"该层能处理的"异常,其余上抛或转译;兜底层保证不泄漏;吞异常与异常当流程控制是反模式,分别用"记录/传播"与"条件/Result"替代。
异常分层是"责任边界":业务层捕获可恢复、边界层转译、兜底层兜底。反模式是吞异常(静默)与异常当流程控制(昂贵+语义混乱)。正确的分层让异常可处理、可转译、可兜底。
// 吞异常(反模式)
catch (Exception e) { /* 空 */ }
// 异常当流程控制(反模式)
try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; }
// 正确:记录/转译/兜底
catch (DataAccessException e) {
log.error("db error", e);
throw new BusinessException("DB_ERR", e); // 转译
}