返回

SpringBoot实现统一异常处理的正确姿势

后端

好的代码离不开对异常的处理,而恰到好处的异常处理,能让我们对异常的定位更加便捷、快速。SpringBoot作为一款优秀的微服务框架,其内置对异常的处理机制,能帮助我们开发高质量的程序。

实现步骤

  1. 定义统一响应对象类

首先,我们需要定义一个统一的响应对象类,该类将作为所有异常处理的响应结果。该类可以包含以下字段:

public class ApiResponse {

    private int code;

    private String message;

    private Object data;

    public ApiResponse(int code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    // 省略getter和setter方法
}
  1. 定义业务异常枚举接口和实现

接着,我们需要定义一个业务异常枚举接口,该接口将包含所有可能发生的业务异常。每个异常枚举值都应该包含一个错误代码和一个错误信息。例如:

public interface BusinessExceptionEnum {

    int getCode();

    String getMessage();

}

public enum CommonBusinessExceptionEnum implements BusinessExceptionEnum {

    // 系统错误
    SYSTEM_ERROR(500, "系统错误"),

    // 参数错误
    PARAMETER_ERROR(400, "参数错误"),

    // 业务错误
    BUSINESS_ERROR(1000, "业务错误");

    private int code;

    private String message;

    CommonBusinessExceptionEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }

    @Override
    public int getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }
}
  1. 定义业务异常基类

然后,我们需要定义一个业务异常基类,该基类将继承自RuntimeException,并实现BusinessExceptionEnum接口。该基类将作为所有业务异常的父类,并提供一些公共的方法和属性。例如:

public abstract class BusinessException extends RuntimeException implements BusinessExceptionEnum {

    private static final long serialVersionUID = 1L;

    public BusinessException() {
        super();
    }

    public BusinessException(String message) {
        super(message);
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }

    public BusinessException(Throwable cause) {
        super(cause);
    }

    protected BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    @Override
    public abstract int getCode();

    @Override
    public abstract String getMessage();

}
  1. 定义全局异常处理切面

接下来,我们需要定义一个全局异常处理切面,该切面将拦截所有未处理的异常,并将其转换为统一的响应对象。该切面可以如下所示实现:

@Aspect
@Component
public class GlobalExceptionHandler {

    @Around("execution(* com.example.demo.*.*(..))")
    public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            // 如果是业务异常,直接返回业务异常的响应对象
            if (e instanceof BusinessException) {
                BusinessException businessException = (BusinessException) e;
                return new ApiResponse(businessException.getCode(), businessException.getMessage(), null);
            }

            // 如果是系统异常,返回系统异常的响应对象
            return new ApiResponse(500, "系统错误", null);
        }
    }

}
  1. 测试和验证

最后,我们需要对统一异常处理进行测试和验证,以确保其正常工作。我们可以编写一些测试用例,来测试不同类型的异常是否能够被正确处理。例如:

@SpringBootTest
public class GlobalExceptionHandlerTest {

    @Autowired
    private GlobalExceptionHandler globalExceptionHandler;

    @Test
    public void testBusinessException() {
        BusinessException businessException = new CommonBusinessExceptionEnum.BusinessError();
        ApiResponse response = globalExceptionHandler.handleException(null, businessException);
        Assertions.assertEquals(response.getCode(), 1000);
        Assertions.assertEquals(response.getMessage(), "业务错误");
    }

    @Test
    public void testSystemException() {
        Exception exception = new Exception();
        ApiResponse response = globalExceptionHandler.handleException(null, exception);
        Assertions.assertEquals(response.getCode(), 500);
        Assertions.assertEquals(response.getMessage(), "系统错误");
    }

}

总结

通过以上步骤,我们就可以在SpringBoot中实现统一异常处理。统一异常处理可以使我们的代码更加健壮、易于维护,并且可以提高系统的可用性。