SpringMVC 异常处理笔记

核心原则:异常处理有明确的优先级,推荐使用全局异常处理器统一管理,避免代码冗余。

一、异常处理的三种核心方式

按使用范围和优先级,分为以下三类,优先级从高到低排列。

1. 控制器(Controller)本类处理

在发生异常的 Controller 内部,通过@ExceptionHandler注解定义方法,专门处理当前类的异常。

  • 核心特点:仅作用于当前 Controller,优先级最高。
  • 适用场景:当前 Controller 有特殊的异常处理逻辑,与其他 Controller 不同时使用。
  • 代码示例(来自 HelloController):
1
2
3
4
5
// 处理当前类的算术异常(如10/0)
@ExceptionHandler(ArithmeticException.class)
public R handleArithmeticException(ArithmeticException e){
return R.error(100,"执行异常" + e.getMessage());
}

2. 全局异常处理

通过@RestControllerAdvice(或@ControllerAdvice + @ResponseBody)定义全局组件,处理整个应用中所有未被本类处理的异常。

  • 核心特点:作用于整个应用,优先级低于 “本类处理”,高于 “SpringMVC 兜底处理”。
  • 适用场景:处理应用中通用的异常(如空指针、数据库异常),是企业开发的最佳实践。
  • 代码示例(来自 GlobalExceptionHandler):
1
2
3
4
5
6
7
8
9
// 全局组件注解,等同于 @ControllerAdvice + @ResponseBody
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理所有Exception类型异常(最宽泛的异常)
@ExceptionHandler(Exception.class)
public R error(Exception e){
return R.error(500,"执行异常" + e.getMessage());
}
}

3. SpringMVC 兜底处理

当异常未被 “本类处理” 和 “全局处理” 捕获时,由 SpringMVC 框架默认处理。

  • 核心特点:框架自带,无自定义能力,返回默认的错误页面或错误信息。
  • 适用场景:仅作为最后的兜底,不推荐依赖,应通过全局处理器覆盖。

二、异常处理的关键优先级规则

  1. 范围优先级本类处理 > 全局处理 > SpringMVC 兜底处理
    • 示例:HelloController 的算术异常,优先被本类的handleArithmeticException处理,不会走到全局处理器。
  2. 精度优先级精确异常类型 > 宽泛异常类型
    • 示例:ArithmeticException(算术异常)是 Exception(通用异常)的子类,发生算术异常时,会优先匹配@ExceptionHandler(ArithmeticException.class),而非@ExceptionHandler(Exception.class)

三、企业开发最佳实践

  1. 优先使用全局异常处理器:将所有通用异常(如参数错误、数据库异常、IO 异常)统一在全局处理器中处理,减少代码冗余。
  2. 特殊情况用本类处理:仅当某个 Controller 有特殊异常逻辑时,在该类内部补充定义,覆盖全局处理。
  3. 避免编程式异常处理:如try-catch代码块,大量使用会导致业务代码臃肿、可读性差,应通过注解式处理替代(参考 HelloController 中被注释的 try-catch 代码)。