全局异常处理器

在 Java 开发中(尤其是 Spring 框架中),全局异常处理器 是一种集中处理应用程序中所有未捕获异常的机制。它可以帮助开发者统一异常响应格式、简化代码、提升可维护性。

在做web开发时,通常开发人员都会自定义一些返回状态码以及对应的状态信息的枚举类(接下来统称为ResultCodeEnum)。而这些ResultCodeEnum不仅仅可以Cotroller层中将响应结果响应给前端,同样也用在通用异常/自定义异常 中,将异常信息响应给前端。但是为了将异常信息响应给前端,就需要开发人员在每一个需要捕获通用异常/自定义异常的Controller层中使用try-catch进行捕获和响应,这就会造成大量的代码复用,也会加大开发人员的压力,无法专注于业务。这时就可以使用全局异常处理器,帮助开发人员统一处理这些异常并响应给前端。

1. 为什么需要全局异常处理器

  1. 统一异常响应格式 避免每个控制器方法都写重复的 try-catch 代码,返回统一的 JSON 结构(如 { code, message, data })。

  2. 集中管理异常逻辑 将异常处理与业务逻辑解耦,代码更清晰。

  3. 提升用户体验 客户端能收到结构化的错误信息(如错误码、友好提示)。

  4. 日志记录 可全局记录异常日志,便于排查问题。

2. Spring中全局异常处理器的实现

2.1 定义全局异常处理器

在Spring 提供了 @ControllerAdvice 和 @ExceptionHandler 注解来实现全局异常处理。

以下使用全局异常处理器的情况为:响应给前端的结果为自定义的响应类Result和自定义的异常类MyException,更多使用情况可参考官方文档。

java 复制代码
@ControllerAdvice // 标记为全局异常处理器
public class GlobalExceptionHandler {
    @ExceptionHandler(MyException.class) // 处理通用异常Exception
    @ResponseBody // // 处理通用异常Exception
    public Result error(Exception e){
        e.printStackTrace();
        return Result.fail(); // 返回自定义响应类的失败状态
    }
}

也可以使用@RestControllerAdvice ,相当于 @ControllerAdvice + @ResponseBody

2.2 自定义异常类MyException

java 复制代码
@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();
    }
​
    @Override
    public String toString() {
        return "LeaseException{" +
                "code=" + code +
                ", message=" + this.getMessage() +
                '}';
    }
}

2.3 在全局异常处理器中增加自定义异常类的处理逻辑

java 复制代码
@ControllerAdvice // 标记为全局异常处理器
public class GlobalExceptionHandler {
    @ExceptionHandler(MyException.class) // 处理通用异常Exception
    @ResponseBody // // 处理通用异常Exception
    public Result error(Exception e){
        e.printStackTrace();
        return Result.fail(); // 返回自定义响应类的失败状态
    }
  
  // 增加自定义异常类的处理逻辑
  @ExceptionHandler(LeaseException.class)
  @ResponseBody
  public Result error(LeaseException e){
      e.printStackTrace();
      return Result.fail(e.getCode(), e.getMessage());
  }
}
  • Result类中fail()方法的处理逻辑:
java 复制代码
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 全局异常处理器使用场景详解

复制代码
  
java 复制代码
  if (count > 0) {
        throw new MyException(ResultCodeEnum.UNLOG_ERROR);
    }
  • 假设在在业务代码中,判断count是否大于0,如果大于0就抛出自定义异常并响应异常信息给前端

  • 通过响应结果枚举对象构造自定义异常对象。

  • 抛出自定义异常后,全局异常处理器会捕获到该异常(因为定义全局异常处理器时,添加了@ExceptionHandler(MyException.class))。

  • 全局异常处理器就会根据定义好的处理逻辑对异常进行处理。

2.5 注意

  • 全局异常处理功能由SpringMVC提供,因此需要在Spring Boot的pom.xml中引入如下依赖:
XML 复制代码
<!--spring-web-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 优先处理具体异常 将具体的异常处理(如 NullPointerException)放在通用异常(如 Exception)之前,避免后者覆盖前者。
  • 自定义异常层级 设计业务异常继承体系(如 BusinessException, ValidationException),便于分类处理。

3. 全局异常处理器的优点

  1. 统一异常响应格式,提升用户体验。

  2. 集中管理异常逻辑,减少代码冗余。

  3. 灵活处理各类异常(参数校验、数据库错误、业务异常等)。

  4. 完善日志记录,方便问题排查。

相关推荐
我命由我1234539 分钟前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
苜蓿muxu1 小时前
Java 字符串拼接:+、StringBuilder、StringBuffer的区别
java
摇滚侠1 小时前
《Java并发编程之美》第 4 章 Java 并发包中原子操作类原理剖析 阅读笔记 7
java·笔记·python
旋律4142 小时前
同义方法区别(增加类与删除类)
java·后端
学到老活到老2 小时前
方法执行完了,对象为什么还占着内存?
java·jvm
用户7771298509122 小时前
常见的同义方法的区别:增加类和删除类
java·后端
十年Java程序媛2 小时前
Java this 与 super 详解|继承高频踩坑 + 面试题整理
java·spring boot·面试
用户7771298509122 小时前
Stream流式使用
java
旋律4142 小时前
List、Set、Map:三个装数据的容器,到底啥区别?怎么遍历?
java·后端