前言
在SpringBoot项目的日常构建中,异常处理是确保应用稳定运行的关键一环。然而,仅仅依赖框架自带的异常处理机制往往无法满足我们对代码质量和可维护性的高要求。因此,实现自定义异常处理,以更加高效、准确地捕获和处理异常,成为了我们追求的目标。
下面,我们将介绍一种通过@ControllerAdvice
和@ExceptionHandler
注解实现SpringBoot自定义异常处理的方法,并附上具体的代码示例。
异常处理方式一
1.1 自定义全局异常类
首先,我们需要创建一个自定义的全局异常类,用于封装项目中可能出现的特定异常信息。这个类可以继承自RuntimeException
或Exception
,并添加必要的属性来存储异常信息。
// 自定义全局异常类
public class CustomGlobalException extends RuntimeException {
private int errorCode;
private String errorMessage;
public CustomGlobalException(int errorCode, String errorMessage) {
super(errorMessage);
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
// Getter 和 Setter 方法
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
1.2 手动抛出异常
在业务逻辑中,当检测到错误条件时,我们可以手动抛出这个自定义的全局异常。
// 示例业务逻辑代码
public void someBusinessLogic() {
// 假设有一个条件触发了异常
boolean errorCondition = true;
if (errorCondition) {
throw new CustomGlobalException(400, "Bad Request: Some error occurred");
}
// 其他业务逻辑
}
1.3 测试打印
为了验证异常处理机制是否工作正常,我们可以在捕获异常的地方打印异常信息。
public static void main(String[] args) {
try {
someBusinessLogic();
} catch (CustomGlobalException e) {
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Error Message: " + e.getErrorMessage());
}
}
异常处理方式二
2.1 定义基础接口类
定义一个基础接口类,用于规范异常处理中可能需要的通用方法或属性。
// 基础接口类(可选)
public interface BaseErrorResponse {
int getStatus();
String getMessage();
}
2.2 定义枚举类
定义一个枚举类,用于封装异常处理中可能需要的错误代码和错误消息。
// 错误代码枚举类
public enum ErrorCode {
BAD_REQUEST(400, "Bad Request"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error");
private int code;
private String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
// Getter 方法
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
2.3 自定义异常类
与方式一类似,但这次我们可能会使用枚举类来设置错误代码和消息。
// 自定义异常类(使用枚举类)
public class EnumCustomException extends RuntimeException {
private int errorCode;
private String errorMessage;
public EnumCustomException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode.getCode();
this.errorMessage = errorCode.getMessage();
}
// Getter 和 Setter 方法
public int getErrorCode() {
return errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
}
2.4 自定义数据传输
定义一个数据传输对象(DTO),用于封装异常处理中返回给客户端的错误信息。
// 自定义数据传输对象
public class ErrorResponseDTO implements BaseErrorResponse {
private int status;
private int errorCode;
private String message;
public ErrorResponseDTO(int status, int errorCode, String message) {
this.status = status;
this.errorCode = errorCode;
this.message = message;
}
// Getter 方法
@Override
public int getStatus() {
return status;
}
public int getErrorCode() {
return errorCode;
}
@Override
public String getMessage() {
return message;
}
}
2.5 自定义全局异常处理
使用@ControllerAdvice
和@ExceptionHandler
注解来定义全局异常处理类。
// 全局异常处理类
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(EnumCustomException.class)
public ResponseEntity<ErrorResponseDTO> handleEnumCustomException(EnumCustomException ex) {
ErrorResponseDTO errorResponse = new ErrorResponseDTO(
ex.getErrorCode(),
ex.getErrorCode(), // 这里直接使用异常中的错误代码作为示例
ex.getErrorMessage()
);
return new ResponseEntity<>(errorResponse, HttpStatus.valueOf(ex.getErrorCode()));
}
// 可以添加其他异常处理方法来处理不同类型的异常
}
2.6 测试代码
编写测试代码来验证全局异常处理机制是否工作正常。
// 测试代码
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/exception")
public ResponseEntity<String> testException() {
throw new EnumCustomException(ErrorCode.BAD_REQUEST);
}
}
然后,通过访问/test/exception
端点来触发异常,并观察返回的JSON响应是否符合预期。
总结
通过实现全局异常处理机制,我们能够以统一的方式处理项目中可能出现的各种异常,提高代码的可读性和可维护性。无论是使用简单的自定义异常类,还是结合枚举类和数据传输对象来构建更复杂的异常处理体系,都能够有效地提升异常处理的效率和准确性。