一、引言
在开发基于 Spring Boot 的应用程序时,异常处理是一个不可忽视的重要环节。良好的异常处理机制可以提高系统的健壮性和可维护性,同时为用户和开发者提供更友好的错误反馈。在传统的开发中,我们可能会在每个控制器方法中编写大量的异常处理代码,这样会导致代码冗余且难以维护。Spring Boot 提供了强大的异常统一处理机制,通过使用注解和特定的类,我们可以将异常处理逻辑集中管理,避免代码重复,提高开发效率。
二、Spring Boot 异常处理基础
在 Spring Boot 中,异常处理主要基于两个核心概念:@ControllerAdvice 和 @ExceptionHandler。
2.1 @ControllerAdvice
@ControllerAdvice 是一个特殊的 @Component,用于定义 @ExceptionHandler、@InitBinder 和 @ModelAttribute 方法,这些方法将应用到所有使用 @RequestMapping 注解的控制器类中的方法。简单来说,@ControllerAdvice 是一个全局的异常处理类,它可以捕获所有控制器中抛出的异常。
2.2 @ExceptionHandler
@ExceptionHandler 注解用于指定处理特定异常的方法。当控制器方法抛出指定类型的异常时,Spring Boot 会自动调用被 @ExceptionHandler 注解标注的方法来处理该异常。
三、实现异常统一处理的步骤
3.1 创建自定义异常类
首先,我们可以创建自定义异常类,以便在业务逻辑中抛出特定类型的异常。例如:
public class CustomException extends RuntimeException {
private int code;
private String message;
public CustomException(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
3.2 创建全局异常处理类
使用 @ControllerAdvice 和 @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;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException ex) {
return new ResponseEntity<>("Custom Exception: Code - " + ex.getCode() + ", Message - " + ex.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGeneralException(Exception ex) {
return new ResponseEntity<>("General Exception: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在上述代码中,GlobalExceptionHandler 类使用 @ControllerAdvice 注解,表明它是一个全局异常处理类。handleCustomException 方法使用 @ExceptionHandler 注解,专门处理 CustomException 类型的异常,返回一个包含异常信息的 ResponseEntity 对象,状态码为 400 Bad Request。handleGeneralException 方法处理所有其他类型的异常,返回一个包含异常信息的 ResponseEntity 对象,状态码为 500 Internal Server Error。
3.3 在控制器中抛出异常
创建一个简单的控制器,在其中抛出异常:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
throw new CustomException(1001, "This is a custom exception");
}
}
当访问 /test 接口时,控制器方法会抛出 CustomException 异常,该异常会被 GlobalExceptionHandler 类中的 handleCustomException 方法捕获并处理。
四、返回统一的错误响应格式
为了让前端更容易处理错误信息,我们可以定义一个统一的错误响应格式。
4.1 创建错误响应类
public class ErrorResponse {
private int code;
private String message;
public ErrorResponse(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
4.2 修改全局异常处理类
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex) {
ErrorResponse errorResponse = new ErrorResponse(ex.getCode(), ex.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse(500, ex.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
现在,异常处理方法返回的是包含 ErrorResponse 对象的 ResponseEntity,前端可以根据 ErrorResponse 中的 code 和 message 字段来处理错误信息。
五、总结
通过使用 @ControllerAdvice 和 @ExceptionHandler 注解,我们可以在 Spring Boot 中实现异常的统一处理。这种方式将异常处理逻辑集中管理,避免了代码冗余,提高了系统的可维护性。同时,定义统一的错误响应格式可以让前端更容易处理错误信息,提升用户体验。在实际开发中,我们可以根据业务需求创建更多的自定义异常类,并在全局异常处理类中添加相应的处理方法。