全局异常处理器
在 Java 开发中(尤其是 Spring 框架中),全局异常处理器是一种集中处理应用程序中所有未捕获异常的机制。它可以帮助开发者统一异常响应格式、简化代码、提升可维护性。
在做web开发时,通常开发人员都会自定义一些返回状态码以及对应的状态信息的枚举类(接下来统称为ResultCodeEnum
)。而这些ResultCodeEnum
不仅仅可以Cotroller
层中将响应结果响应给前端,同样也用在通用异常/自定义异常中,将异常信息响应给前端。但是为了将异常信息响应给前端,就需要开发人员在每一个需要捕获通用异常/自定义异常的Controller
层中使用try-catch
进行捕获和响应,这就会造成大量的代码复用,也会加大开发人员的压力,无法专注于业务。这时就可以使用全局异常处理器,帮助开发人员统一处理这些异常并响应给前端。
1. 为什么需要全局异常处理器
-
统一异常响应格式 避免每个控制器方法都写重复的
try-catch
代码,返回统一的 JSON 结构(如{ code, message, data }
)。 -
集中管理异常逻辑 将异常处理与业务逻辑解耦,代码更清晰。
-
提升用户体验 客户端能收到结构化的错误信息(如错误码、友好提示)。
-
日志记录 可全局记录异常日志,便于排查问题。
2. Spring中全局异常处理器的实现
2.1 定义全局异常处理器
在Spring 提供了 @ControllerAdvice
和 @ExceptionHandler
注解来实现全局异常处理。
以下使用全局异常处理器的情况为:响应给前端的结果为自定义的响应类
Result
和自定义的异常类MyException
,更多使用情况可参考官方文档。
@ControllerAdvice // 标记为全局异常处理器
public class GlobalExceptionHandler {@ExceptionHandler(MyException.class) // 处理通用异常Exception@ResponseBody // // 处理通用异常Exceptionpublic Result error(Exception e){e.printStackTrace();return Result.fail(); // 返回自定义响应类的失败状态}
}
也可以使用
@RestControllerAdvice
,相当于 @ControllerAdvice + @ResponseBody
2.2 自定义异常类MyException
@Data
public class MyException extends RuntimeException {
//异常状态码private Integer code;/*** 通过状态码和错误消息创建异常对象* @param message* @param code*/public LeaseException(String message, Integer code) {super(message);this.code = code;}
/*** 根据响应结果枚举对象创建异常对象* @param resultCodeEnum*/public LeaseException(ResultCodeEnum resultCodeEnum) {super(resultCodeEnum.getMessage());this.code = resultCodeEnum.getCode();}
@Overridepublic String toString() {return "LeaseException{" +"code=" + code +", message=" + this.getMessage() +'}';}
}
2.3 在全局异常处理器中增加自定义异常类的处理逻辑
@ControllerAdvice // 标记为全局异常处理器
public class GlobalExceptionHandler {@ExceptionHandler(MyException.class) // 处理通用异常Exception@ResponseBody // // 处理通用异常Exceptionpublic Result error(Exception e){e.printStackTrace();return Result.fail(); // 返回自定义响应类的失败状态}// 增加自定义异常类的处理逻辑@ExceptionHandler(LeaseException.class)@ResponseBodypublic Result error(LeaseException e){e.printStackTrace();return Result.fail(e.getCode(), e.getMessage());}
}
-
Result
类中fail()方法的处理逻辑:
public static <T> Result<T> fail(Integer code, String message) {Result<T> result = build(null); // build()方法是用于构造Result类的,使用了构造工厂模式result.setCode(code);result.setMessage(message);return result;
}
2.4 全局异常处理器使用场景详解
if (count > 0) {throw new MyException(ResultCodeEnum.UNLOG_ERROR);}
-
假设在在业务代码中,判断count是否大于0,如果大于0就抛出自定义异常并响应异常信息给前端
-
通过响应结果枚举对象构造自定义异常对象。
-
抛出自定义异常后,全局异常处理器会捕获到该异常(因为定义全局异常处理器时,添加了
@ExceptionHandler(MyException.class)
)。 -
全局异常处理器就会根据定义好的处理逻辑对异常进行处理。
2.5 注意
-
全局异常处理功能由SpringMVC提供,因此需要在Spring Boot的
pom.xml
中引入如下依赖:
<!--spring-web-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
-
优先处理具体异常 将具体的异常处理(如
NullPointerException
)放在通用异常(如Exception
)之前,避免后者覆盖前者。
-
自定义异常层级 设计业务异常继承体系(如
BusinessException
,ValidationException
),便于分类处理。
3. 全局异常处理器的优点
-
统一异常响应格式,提升用户体验。
-
集中管理异常逻辑,减少代码冗余。
-
灵活处理各类异常(参数校验、数据库错误、业务异常等)。
-
完善日志记录,方便问题排查。