SpringBoot自定义全局异常处理

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

自定义全局异常处理

我们在 SpringBoot 项目中往往会写许多 Controler 接口类由于 Controller
类接口中传递的参数各不相同出现错误时抛出的异常以及异常的处理方式也不尽相同。

java程序中异常有很多种所有异常的父类都是Throwable类其中Exception异常是可以进行手动处理的在程序运行过程中也会出现各种业务异常需要自定义可能返回500,404等等前端拿到这些异常可能不方便处理如果可以统一一个全局异常是什么错误就返回什么信息和code码给前端前端更便于处理。

一. 创建所需类

1. 自定义异常接口

为了代码解耦创建一个接口类出来定义自定义接口所需要的方法

/**
 * @author gf
 * @date 2023/2/2
 */
// 第一步为了代码解耦创建一个接口类出来定义自定义接口所需要的方法
// 抽象类提供自定义异常所需的方法
public interface BaseErrorInfoInterface {

    String getCode();

    String getMessage();
}

2. 自定义枚举类

定义一个枚举类实现上述BaseErrorInfoInterface接口重写上述接口的两个方法来操作这个枚举类内部的各个具体枚举值

/**
 * @author gf
 * @date 2023/2/2
 */
//第二步定义一个枚举类实现上述接口重写上述接口的两个方法来操作这个枚举类内部的各个具体枚举值
public enum BaseErrorEnum implements BaseErrorInfoInterface {

    //定义异常枚举
    SUCCESS("200","成功"),
    USER_NOT_EXIST("1001","用户不存在");

    // 错误码
    private String code;
    // 错误信息提示
    private String message;

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

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

    @Override
    public String getMessage() {
        return message;
    }
}

后续方便管理所有错误枚举的错误信息以及code码通过构造方法传入code值和message或者直接传入一个枚举值都行

3. 自定义异常类

自定义一个异常类就像空指针异常类、IO流异常类一样。此处自定义的异常类属于异常类所有肯定是要继承一个异常类的此处需要继承RuntimeException原因如下

RuntimeException相比Exception来讲他是在程序运行时才会爆出异常在编译时是不会出现异常的这就表示如果你throw了一个RuntimeException不需要做额外操作而throw一个Exception程序会要求你try-catch否则你根本启动不了程序程序会提示必须对其进行捕获或声明以便抛出。

@Data
public class BaseException extends RuntimeException {

    // 错误码
    private String code;
    // 错误信息提示
    private String message;

    public BaseException(){
        super();
    }
    // 自定义异常构造方法
    public BaseException(BaseErrorEnum baseErrorEnum){
        super(baseErrorEnum.getCode());
        this.code=baseErrorEnum.getCode();
        this.message=baseErrorEnum.getMessage();
    }
}

4. 自定义异常处理类

/**
 - @author gf
 - @date 2023/2/2
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理自定义异常
    @ExceptionHandler({BaseException.class})
    public BaseResponse<Object> baseExceptionHandler(BaseException e) {
        log.debug("请求错误{}", e.getMessage());
        return RespGenerator.failure(e.getCode(), e.getMessage());
    }

    // 处理空指针异常
    @ExceptionHandler({NullPointerException.class})
    public BaseResponse<Object>  exceptionHandler(NullPointerException e) {
        log.error("运行时异常{}", e.getMessage());
        return RespGenerator.failure(BaseErrorEnum.USER_NOT_EXIST);
    }

    // 处理其他异常
    @ExceptionHandler({Exception.class})
    public BaseResponse<Object>  exceptionHandler(Exception exception) {
        log.error("未知异常{}", exception);
        return RespGenerator.failure("500", "系统未知异常");
    }
}

注解说明

  • @ControllerAdvice注解结合方法型注解@ExceptionHandler用于捕获Controller中抛出的指定类型的异常从而达到不同类型的异常区别处理的目的。
  • @ExceptionHandler注解 统一处理某一类异常从而能够减少代码重复率和复杂度value值为什么异常类型就处理什么异常类型的逻辑。

5. 自定义全局响应类

上面使用的方法返回值类BaseResponse类和RespGenerator类都是属于规范方法返回值结构体的类也有利于一致化后端所有接口的返回结构方便前端读取所需要的数据。

5.1 BaseResponse类

规定返回值结构

/**
 * @author gf
 * @date 2023/2/2
 */
@Data
public class BaseResponse<T> {

    private String code;

    private String messgae;

    private T Data;

    public BaseResponse() {
        super();
    }
    public BaseResponse(String code, String messgae, T data) {
        this.code = code;
        this.messgae = messgae;
        Data = data;
    }
}

5.2 RespGenerator类

将逻辑处理后的数据包装转换成BaseResponse类进行返回给前端。

/**
 * @author gf
 * @date 2023/2/2
 */
public class RespGenerator {

    // 正常返回时调用方法
    public static BaseResponse success(Object data){
        return new BaseResponse(BaseErrorEnum.SUCCESS.getCode(),"接口调用成功",data);
    }
    // 失败时调用方法
    public static  BaseResponse<Object> failure(BaseErrorEnum baseErrorEnum){
        return new BaseResponse(baseErrorEnum.getCode(),baseErrorEnum.getMessage(),null);
    }

    // 失败时调用方法(提供给GlobalExceptionHandler类使用)
    public static BaseResponse<Object> failure(String code,String message){
        return new BaseResponse(code,message,null);
    }

}

二. 效果演示

创建测试类

@RestController
public class ExceptionTest {

    @GetMapping("/test")
    public BaseResponse<String> sayHello(@RequestParam("name") String name){
        if(!name.equals("老王")){
            throw new BaseException(BaseErrorEnum.USER_NOT_EXIST);
        }
        else{
            return RespGenerator.success("调用成功");
        }
    }
}

从代码中可以看到若name不是老王会抛出自定义异常
在这里插入图片描述

如果姓名时老王则返回成功

在这里插入图片描述
-----------------------------------------------------完毕----------------------------------------------------------

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring