目录
- 一、全局异常处理的作用
- 二、Spring Boot 实现全局异常处理(附上代码实例)
- 三、总结:
🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解SpringBoot的Bean请看: 从乐高积木到乐队指挥,用最通俗易懂的方式带你玩转 Spring Boot Bean!
✨更多请看个人主页: 码熔burning
咱今儿个就来好好讲解一下SpringBoot的全局异常处理,保证你听得懂,会写,会用😁!
一、全局异常处理的作用
想象一下,你开了一家餐厅 🍽️。
-
没有全局异常处理: 如果你的厨师 👨🍳 在做菜的时候,不小心把盐放多了 🧂,或者烤箱 🔥 突然坏了,导致菜做砸了 😫。顾客吃到难吃的菜,会直接抱怨 🗣️,甚至直接走人 🚶♀️,餐厅的声誉就受损了 📉。而且,你可能不知道具体是哪个环节出了问题 🤔,下次还可能犯同样的错误 🤦。
-
有全局异常处理: 你安排了一个“危机公关”团队 🦸♀️🦸♂️,专门处理这些突发情况。
- 如果厨师做菜出错,危机公关团队会立刻介入 🏃♀️,给顾客道歉 🙏,提供补偿(比如打折 💰、换菜 🔄),尽量安抚顾客的情绪 😊。
- 同时,危机公关团队会记录下出错的原因 📝(盐放多了、烤箱坏了),反馈给厨师和设备维护人员 🛠️,避免下次再犯 🚫。
- 即使顾客非常生气 😡,危机公关团队也能保持冷静 🧘♀️,用专业的态度处理问题 🤝,尽量维护餐厅的形象 💯。
总结: 全局异常处理就像餐厅的“危机公关”团队,它的作用是:
- 兜底: 当程序出现未预料的错误(异常)时,防止程序崩溃 💥,给用户一个友好的提示 💬,而不是让用户看到一堆乱七八糟的错误代码 😵💫。
- 统一处理: 将所有异常集中到一个地方处理 📍,方便记录日志 🪵、发送报警 🚨、返回统一的错误格式 🏷️,避免代码重复 ♻️。
- 提升用户体验: 给用户更友好的错误提示 😃,而不是让用户看到技术性的错误信息 🤓。
- 方便维护: 方便开发人员定位问题 🔍,改进代码 💻,提高程序的健壮性 💪。
二、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;
}
}
代码解释:
@ControllerAdvice
: 告诉 Spring,这是一个全局异常处理类 📣。@ExceptionHandler(value = BusinessException.class)
: 告诉 Spring,handleBusinessException
方法专门处理BusinessException
类型的异常 🎯。value
属性指定了要处理的异常类型。@ResponseBody
: 告诉 Spring,将方法的返回值转换为 JSON 格式 📦,返回给客户端。ResponseEntity<Map<String, Object>>
: 方法的返回值类型,表示返回一个包含错误信息的 JSON 对象 🧾,以及 HTTP 状态码。handleBusinessException(BusinessException e)
: 异常处理方法,接收一个BusinessException
类型的参数e
,表示捕获到的异常对象 🎣。 你可以在这里获取异常的信息,并进行处理 ⚙️。Map<String, Object> errorInfo
: 创建一个 Map 对象 🗺️,用于存储错误信息,例如错误码、错误消息等。new ResponseEntity<>(errorInfo, HttpStatus.BAD_REQUEST)
: 创建一个ResponseEntity
对象 🎁,包含错误信息和 HTTP 状态码。HttpStatus.BAD_REQUEST
表示 400 错误 ❌,表示客户端请求有误。handleException(Exception e)
: 处理所有未知的异常 🤷♀️,这是一个兜底方案 🛡️,防止程序崩溃 💥。
如何使用:
-
创建自定义异常类 (可选): 例如上面的
BusinessException
,你可以根据业务需求创建自己的异常类 ✏️。 -
在 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; } }
-
启动 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” 😊。
三、总结:
- 使用
@ControllerAdvice
创建一个全局异常处理类 🏥。 - 使用
@ExceptionHandler
注解指定处理特定类型的异常的方法 🎯。 - 在异常处理方法中,获取异常信息 ℹ️,并返回统一的错误格式 🏷️ 给客户端。
- 可以自定义异常类 ✏️,方便处理业务逻辑中的错误。
更进一步:
- 日志记录: 在异常处理方法中,可以使用日志框架(例如 Logback、Log4j)记录异常信息 🪵,方便排查问题 🔍。
- 发送报警: 当发生严重错误时,可以发送邮件 📧、短信 📱 等报警信息给开发人员 👨💻👩💻。
- 统一错误码: 定义一套统一的错误码规范 🔢,方便客户端识别和处理错误。
- AOP 方式: 除了
@ControllerAdvice
,还可以使用 AOP (面向切面编程) 来实现全局异常处理,更加灵活 🤸。
希望这篇文章的讲解能够帮助你理解 Spring Boot 的全局异常处理 。 记住,全局异常处理是提高程序健壮性和用户体验的重要手段 。 多练习 🏋️♀️,多实践 ,你就能掌握它! 🎉