Spring Boot全局异常处理:“危机公关”团队

Spring Boot全局异常处理:“危机公关”团队_第1张图片

目录

    • 一、全局异常处理的作用
    • 二、Spring Boot 实现全局异常处理(附上代码实例)
    • 三、总结:

我的其他文章也讲解的比较有趣,如果喜欢博主的讲解方式,可以多多支持一下,感谢!
了解SpringBoot的Bean请看: 从乐高积木到乐队指挥,用最通俗易懂的方式带你玩转 Spring Boot Bean!
✨更多请看个人主页: 码熔burning

咱今儿个就来好好讲解一下SpringBoot的全局异常处理,保证你听得懂,会写,会用!

一、全局异常处理的作用

想象一下,你开了一家餐厅 ️。

  • 没有全局异常处理: 如果你的厨师 ‍ 在做菜的时候,不小心把盐放多了 ,或者烤箱 突然坏了,导致菜做砸了 。顾客吃到难吃的菜,会直接抱怨 ️,甚至直接走人 ‍♀️,餐厅的声誉就受损了 。而且,你可能不知道具体是哪个环节出了问题 ,下次还可能犯同样的错误 。

  • 有全局异常处理: 你安排了一个“危机公关”团队 ‍♀️‍♂️,专门处理这些突发情况。

    • 如果厨师做菜出错,危机公关团队会立刻介入 ‍♀️,给顾客道歉 ,提供补偿(比如打折 、换菜 ),尽量安抚顾客的情绪 。
    • 同时,危机公关团队会记录下出错的原因 (盐放多了、烤箱坏了),反馈给厨师和设备维护人员 ️,避免下次再犯 。
    • 即使顾客非常生气 ,危机公关团队也能保持冷静 ‍♀️,用专业的态度处理问题 ,尽量维护餐厅的形象 。

总结: 全局异常处理就像餐厅的“危机公关”团队,它的作用是:

  1. 兜底: 当程序出现未预料的错误(异常)时,防止程序崩溃 ,给用户一个友好的提示 ,而不是让用户看到一堆乱七八糟的错误代码 ‍。
  2. 统一处理: 将所有异常集中到一个地方处理 ,方便记录日志 、发送报警 、返回统一的错误格式 ️,避免代码重复 ♻️。
  3. 提升用户体验: 给用户更友好的错误提示 ,而不是让用户看到技术性的错误信息 。
  4. 方便维护: 方便开发人员定位问题 ,改进代码 ,提高程序的健壮性 。

二、Spring Boot 实现全局异常处理(附上代码实例)

Spring Boot 提供了几种实现全局异常处理的方式,最常用的是使用 @ControllerAdvice@ExceptionHandler 注解。

1. @ControllerAdvice (异常处理中心)

  • @ControllerAdvice 就像一个“异常处理中心” ,它会拦截所有 Controller 中抛出的异常 。
  • 你可以把它理解为一个特殊的 Controller ️,专门用来处理异常。

2. @ExceptionHandler (异常处理方法)

  • @ExceptionHandler 就像“异常处理中心”里的“专家” ‍⚕️‍⚕️,每个专家负责处理一种类型的异常 。
  • 你可以用它来指定某个方法专门处理哪种类型的异常 。

代码示例:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice // 声明这是一个全局异常处理类 
public class GlobalExceptionHandler {

    // 处理自定义的业务异常
    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody // 返回 JSON 格式的数据 
    public ResponseEntity<Map<String, Object>> handleBusinessException(BusinessException e) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("code", e.getCode());
        errorInfo.put("message", e.getMessage());

        return new ResponseEntity<>(errorInfo, HttpStatus.BAD_REQUEST); // 返回 400 状态码 ❌
    }

    // 处理空指针异常
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseBody
    public ResponseEntity<Map<String, Object>> handleNullPointerException(NullPointerException e) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("code", "500");
        errorInfo.put("message", "服务器内部错误:空指针异常 ");
        errorInfo.put("detail", e.getMessage()); // 可以记录更详细的错误信息 ℹ️

        return new ResponseEntity<>(errorInfo, HttpStatus.INTERNAL_SERVER_ERROR); // 返回 500 状态码 
    }

    // 处理其他所有未知的异常 (兜底)
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity<Map<String, Object>> handleException(Exception e) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("code", "999");
        errorInfo.put("message", "服务器发生未知错误 ‍♀️");
        errorInfo.put("detail", e.getMessage());

        return new ResponseEntity<>(errorInfo, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 自定义业务异常类
class BusinessException extends RuntimeException {
    private String code;
    private String message;

    public BusinessException(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

代码解释:

  1. @ControllerAdvice: 告诉 Spring,这是一个全局异常处理类 。
  2. @ExceptionHandler(value = BusinessException.class): 告诉 Spring,handleBusinessException 方法专门处理 BusinessException 类型的异常 。 value 属性指定了要处理的异常类型。
  3. @ResponseBody: 告诉 Spring,将方法的返回值转换为 JSON 格式 ,返回给客户端。
  4. ResponseEntity>: 方法的返回值类型,表示返回一个包含错误信息的 JSON 对象 ,以及 HTTP 状态码。
  5. handleBusinessException(BusinessException e): 异常处理方法,接收一个 BusinessException 类型的参数 e,表示捕获到的异常对象 。 你可以在这里获取异常的信息,并进行处理 ⚙️。
  6. Map errorInfo: 创建一个 Map 对象 ️,用于存储错误信息,例如错误码、错误消息等。
  7. new ResponseEntity<>(errorInfo, HttpStatus.BAD_REQUEST): 创建一个 ResponseEntity 对象 ,包含错误信息和 HTTP 状态码。 HttpStatus.BAD_REQUEST 表示 400 错误 ❌,表示客户端请求有误。
  8. handleException(Exception e): 处理所有未知的异常 ‍♀️,这是一个兜底方案 ️,防止程序崩溃 。

如何使用:

  1. 创建自定义异常类 (可选): 例如上面的 BusinessException,你可以根据业务需求创建自己的异常类 ✏️。

  2. 在 Controller 中抛出异常:

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class MyController {
    
        @GetMapping("/test")
        public String test(String input) {
            if (input == null || input.isEmpty()) {
                throw new BusinessException("1001", "输入不能为空 "); // 抛出自定义异常
            }
            if (input.equals("error")) {
                throw new NullPointerException("模拟空指针异常 "); // 抛出空指针异常
            }
            return "Hello, " + input;
        }
    }
    
  3. 启动 Spring Boot 应用: 当 Controller 中抛出异常时,GlobalExceptionHandler 会捕获这些异常 ,并进行处理 ⚙️,返回统一的错误信息给客户端 。

测试:

  • 访问 http://localhost:8080/test?input= (不带参数),会返回一个 400 错误 ❌,包含错误码 “1001” 和错误消息 “输入不能为空 ”。
  • 访问 http://localhost:8080/test?input=error,会返回一个 500 错误 ,包含错误码 “500” 和错误消息 “服务器内部错误:空指针异常 ”。
  • 访问 http://localhost:8080/test?input=world,会正常返回 “Hello, world” 。

三、总结:

  1. 使用 @ControllerAdvice 创建一个全局异常处理类 。
  2. 使用 @ExceptionHandler 注解指定处理特定类型的异常的方法 。
  3. 在异常处理方法中,获取异常信息 ℹ️,并返回统一的错误格式 ️ 给客户端。
  4. 可以自定义异常类 ✏️,方便处理业务逻辑中的错误。

更进一步:

  • 日志记录: 在异常处理方法中,可以使用日志框架(例如 Logback、Log4j)记录异常信息 ,方便排查问题 。
  • 发送报警: 当发生严重错误时,可以发送邮件 、短信 等报警信息给开发人员 ‍‍。
  • 统一错误码: 定义一套统一的错误码规范 ,方便客户端识别和处理错误。
  • AOP 方式: 除了 @ControllerAdvice,还可以使用 AOP (面向切面编程) 来实现全局异常处理,更加灵活 。

希望这篇文章的讲解能够帮助你理解 Spring Boot 的全局异常处理 。 记住,全局异常处理是提高程序健壮性和用户体验的重要手段 。 多练习 ️‍♀️,多实践 ,你就能掌握它!

你可能感兴趣的:(SpringBoot,spring,boot,java,后端)