全局异常处理是Spring Boot项目中非常重要的一部分,它可以帮助我们统一处理各种异常,返回友好的错误信息,提升系统的健壮性和用户体验。以下是详细的全局异常处理代码实现。
全局异常处理类
创建一个全局异常处理类`GlobalExceptionHandler`,使用`@RestControllerAdvice`注解标记该类,并通过`@ExceptionHandler`注解捕获特定异常。
GlobalExceptionHandler.java
package com.example.morningboxspring.exception;
import com.example.morningboxspring.common.Result;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletRequest;
/**
* 功能:GlobalExceptionHandler
* 作者:爱因斯坦乐
* 日期:2025/3/1
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理请求体缺失或格式错误异常
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<String> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpServletRequest request) {
return Result.error(HttpStatus.BAD_REQUEST.value(), "请求体缺失或格式错误: " + ex.getMessage());
}
// 处理参数类型不匹配异常
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<String> handleMethodArgumentTypeMismatch(MethodArgumentTypeMismatchException ex, HttpServletRequest request) {
return Result.error(HttpStatus.BAD_REQUEST.value(), "参数类型不匹配: " + ex.getMessage());
}
// 处理空指针异常
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<String> handleNullPointerException(NullPointerException ex, HttpServletRequest request) {
return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "空指针异常: " + ex.getMessage());
}
// 处理其他未捕获的异常
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<String> handleException(Exception ex, HttpServletRequest request) {
return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误: " + ex.getMessage());
}
}
统一返回结果类
为了统一返回格式,我们可以定义一个通用的返回结果类`Result`。
Result.java
package com.example.morningboxspring.common;
/**
* 功能:Result
* 作者:爱因斯坦乐
* 日期:2025/3/1
*/
public class Result<T> {
private int code; // 状态码
private String message; // 返回信息
private T data; // 返回数据
// 成功返回
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("成功");
result.setData(data);
return result;
}
// 错误返回
public static <T> Result<T> error(int code, String message) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
return result;
}
// Getter 和 Setter
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
测试全局异常处理
测试请求体缺失异常
发送一个`POST`请求,但不提供请求体:
POST http://localhost:8080/user
**响应**:
```json
{
"code": 400,
"message": "请求体缺失或格式错误: Required request body is missing",
"data": null
}
```
测试参数类型不匹配异常
发送一个`GET`请求,路径变量类型错误:
GET http://localhost:8080/user/{1}
**响应**:
```json
{
"code": 400,
"message": "参数类型不匹配: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: \"{1}\"",
"data": null
}
```
测试空指针异常
在代码中模拟一个空指针异常:
```java
@GetMapping("/test-npe")
public Result<String> testNullPointerException() {
String str = null;
return Result.success(str.toLowerCase()); // 触发空指针异常
}
```
发送请求:
GET http://localhost:8080/user/test-npe
**响应**:
```json
{
"code": 500,
"message": "空指针异常: null",
"data": null
}
```
测试其他未捕获的异常
在代码中模拟一个未捕获的异常:
```java
@GetMapping("/test-exception")
public Result<String> testException() {
throw new RuntimeException("测试异常");
}
```
发送请求:
GET http://localhost:8080/user/test-exception
**响应**:
```json
{
"code": 500,
"message": "服务器内部错误: 测试异常",
"data": null
}
```
扩展异常处理
您可以根据项目需求扩展更多的异常处理逻辑。例如:
- **自定义业务异常**:定义自己的业务异常类,并在全局异常处理中捕获。
- **验证异常**:捕获`MethodArgumentNotValidException`,处理参数校验失败的情况。
自定义业务异常
package com.morningbox.exception;
public class BusinessException extends RuntimeException {
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}
捕获自定义业务异常
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<String> handleBusinessException(BusinessException ex, HttpServletRequest request) {
return Result.error(ex.getCode(), ex.getMessage());
}
通过全局异常处理,可以:
1. 统一处理各种异常,返回友好的错误信息。
2. 提升系统的健壮性和用户体验。
3. 根据项目需求扩展更多的异常处理逻辑。