Java中应使用分层多catch块捕获异常并统一包装为含错误码、消息和原始异常的自定义业务异常(如BusinessException),避免重复包装与静默吞没,Spring中推荐@ControllerAdvice集中处理。

Java中使用多个catch块捕获不同异常类型,再统一包装为自定义业务异常,是提升系统可维护性和错误信息一致性的常用做法。
多catch块按异常类型分层捕获
不同异常需区别对待:底层技术异常(如SQLException、IOException)应转换为语义清晰的业务异常;而运行时异常(如NullPointerException)通常反映编程缺陷,可选择记录日志后抛出或直接包装。注意catch顺序——子类异常必须放在父类之前,否则编译不通过。
- 先catch具体异常(如SQLTimeoutException),再catch通用异常(如SQLException)
- 避免用Exception或Throwable作为第一个catch,会掩盖更具体的处理逻辑
- 每个catch块内不做空处理,至少记录日志或明确忽略原因
统一包装为自定义业务异常
定义一个继承RuntimeException的业务异常类(如BusinessException),包含错误码、提示消息、原始异常引用。在catch块中new该异常并传入上下文信息,既保留堆栈追踪,又屏蔽技术细节。
- 构造函数支持传入errorCode、message和cause,便于前端识别和用户理解
- 包装时不丢失原始异常(用initCause或构造函数链式传递),方便排查根因
- 敏感信息(如SQL语句、密码)不可直接拼入message,需脱敏或替换为占位符
避免重复包装与异常吞没
同一异常不应被多次包装,否则堆栈变深、定位困难;也不应在catch后不抛出也不记录,造成“静默失败”。推荐在Service层做统一包装,在Controller层做最终响应封装。
立即学习“Java免费学习笔记(深入)”;
- 已包装过的业务异常,下游模块不再二次包装,而是直接抛出或补充上下文
- catch后若决定不抛出,必须显式记录warn或error级别日志,并说明理由
- 不要用try-catch包裹整个方法体来“兜底”,应聚焦关键易错路径
结合Spring统一异常处理器简化代码
在Spring项目中,可用@ControllerAdvice + @ExceptionHandler集中处理各类异常,把多catch逻辑上移到全局处理器中,保持业务代码干净。
- @ExceptionHandler可分别声明对SQLException、CustomException等的响应策略
- 返回统一Result对象,含code、msg、data字段,前端无需解析多种错误格式
- 配合@ResponseStatus指定HTTP状态码,如400对应参数异常,500对应系统异常


















