SpringBoot封装返回值类,全局捕获异常

前言

这篇文章主要讲解了,基于SpringBoot搭建的前后端分离项目中,如何全局捕获异常,并封装统一的返回值。


一、编写异常信息接口

首先编写一个接口,包含2个抽象方法,分别是获取错误码的方法和获取错误描述的方法。

public interface BaseErrorInfoInterface {
    /**
     * 错误码
     */
    Integer getResultCode();
    /**
     * 错误描述
     */
    String getResultMsg();

}

二、编写错误码枚举类

自定义一个返回值错误码枚举类,这个枚举类实现上面的BaseErrorInfoInterface接口,并重写它的2个抽象方法。 这个枚举类包含3个成员变量,分别为success,code和message,success是boolean类型的,code用于返回错误码,message返回错误信息。随后我们在枚举类中定义了一些常用的返回值,这些返回值在后面的代码中会用到。

@Getter
public enum ResultCodeEnum implements BaseErrorInfoInterface {

    SUCCESS(true, 200, "成功"),
    NULL_POINTER(false, 500, "空指针异常"),
    UN_KNOW(false, 500, "服务器未知内部错误"),
    COMMON_FAIL(false, 5000, "失败");

    private Boolean success;
    private Integer code;
    private String message;

    private ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }

	//重写父接口的抽象方法,返回错误码
    @Override
    public Integer getResultCode() {
        return code;
    }

	//重写父接口的抽象方法,返回错误信息
    @Override
    public String getResultMsg() {
        return message;
    }
}

错误码枚举类写完后,我们需要封装一个返回值的工具类,继续往下看吧。


三、封装返回值工具类

我们姑且把这个返回值工具类命名为Result,其中包含4个成员变量,success、code、message和data。其中success、code和message的数据来自上面创建的枚举类,而data则是HashMap类型的,它用于存放我们要返回给前端的数据。

@Data
public class Result {

    private Boolean success;
    private Integer code;
    private String message;
    private Map<String, Object> data = new HashMap<>();

	//请求成功时的返回值
    public static Result ok() {
        Result r = new Result();
        r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
    }

	//请求失败时的返回值
    public static Result fail() {
        Result r = new Result();
        r.setSuccess(ResultCodeEnum.COMMON_FAIL.getSuccess());
        r.setCode(ResultCodeEnum.COMMON_FAIL.getCode());
        r.setMessage(ResultCodeEnum.COMMON_FAIL.getMessage());
        return r;
    }

    public static Result setResult(ResultCodeEnum resultCodeEnum) {
        Result r = new Result();
        r.setSuccess(resultCodeEnum.getSuccess());
        r.setCode(resultCodeEnum.getCode());
        r.setMessage(resultCodeEnum.getMessage());
        return r;
    }

    public Result success(Boolean success) {
        this.setSuccess(success);
        return this;
    }

    public Result message(String message) {
        this.setMessage(message);
        return this;
    }

    public Result code(Integer code) {
        this.setCode(code);
        return this;
    }

    public Result data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }

    public Result data(Map<String, Object> map) {
        this.setData(map);
        return this;
    }

    public Map<String, Object> toMap() {
        return this.data;
    }

    /**
     * @作者 yangs
     * @日期 2022/1/20
     * @描述 异常时调用
     */
    public static Result error(BaseErrorInfoInterface errorInfo) {
        Result r = new Result();
        r.setSuccess(false);
        r.setCode(errorInfo.getResultCode());
        r.setMessage(errorInfo.getResultMsg());
        return r;
    }

    /**
     * @作者 yangs
     * @日期 2022/1/20
     * @描述 异常时调用
     */
    public static Result error(Integer code, String message) {
        Result r = new Result();
        r.setSuccess(false);
        r.setCode(code);
        r.setMessage(message);
        return r;
    }

    /**
     * @作者 yangs
     * @日期 2022/1/20
     * @描述 异常时调用
     */
    public static Result error(String message) {
        Result r = new Result();
        r.setSuccess(false);
        r.setCode(500);
        r.setMessage(message);
        return r;
    }
    
    private Result() {
    }

    public Result(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }

    /**
     * @作者 yangs
     * @日期 2022/1/20
     * @描述 基于全局异常处理类封装的返回值
     */
    private Result(BaseErrorInfoInterface errorInfo) {
        this.code = errorInfo.getResultCode();
        this.message = errorInfo.getResultMsg();
    }
}

到目前为止,我们已经完成了返回值部分的代码,接下来我们需要自定义一个异常处理类。


四、配置全局异常处理

自定义异常处理类,并继承RuntimeException类,我们可以把自定义的异常类命名为BizException,当我们业务出现错误,程序员可以主动throw 一个BizException,具体用法我们会在后面写一个Controller演示。

/**
 * @作者 yangs
 * @日期 2022/1/20
 * @描述 自定义异常处理类
 */
public class BizException extends RuntimeException {

    /**
     * 错误码
     */
    protected Integer errorCode;

    /**
     * 错误信息
     */
    protected String errorMsg;

    public BizException() {
        super();
    }

    public BizException(BaseErrorInfoInterface errorInfoInterface) {
        super(String.valueOf(errorInfoInterface.getResultCode()));
        this.errorCode = errorInfoInterface.getResultCode();
        this.errorMsg = errorInfoInterface.getResultMsg();
    }

    public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
        super(String.valueOf(errorInfoInterface.getResultCode()), cause);
        this.errorCode = errorInfoInterface.getResultCode();
        this.errorMsg = errorInfoInterface.getResultMsg();
    }

    public BizException(String errorMsg) {
        super(errorMsg);
        this.errorMsg = errorMsg;
    }

    public BizException(Integer errorCode, String errorMsg) {
        super(String.valueOf(errorCode));
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public BizException(Integer errorCode, String errorMsg, Throwable cause) {
        super(String.valueOf(errorCode), cause);
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public Integer getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(Integer errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getMessage() {
        return errorMsg;
    }

    @Override
    public Throwable fillInStackTrace() {
        return this;
    }
}

五、配置全局异常处理

SpringBoot提供了全局异常处理功能,需要借助@ControllerAdvice和@ExceptionHandler注解。@ControllerAdvice用于开启全局异常,它是加在类上面的,而@ExceptionHandler加在方法上,它表示具体捕获哪一种异常。

/**
 * @作者 yangs
 * @日期 2022/1/20
 * @描述 全局异常处理
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义的业务异常,程序员主动抛出BizException异常会被这个方法捕获
     */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public Result bizExceptionHandler(HttpServletRequest req, BizException e) {
        log.error("发生业务异常!原因是:{}", e.getErrorMsg());
        return Result.error(e.getErrorCode(), e.getErrorMsg());
    }

    /**
     * 处理空指针的异常(空指针异常会被这个方法捕获)
     */
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseBody
    public Result exceptionHandler(HttpServletRequest req, NullPointerException e) {
        log.error("发生空指针异常!原因是:", e);
        return Result.error(ResultCodeEnum.NULL_POINTER);
    }

    /**
     * 处理其他异常
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result exceptionHandler(HttpServletRequest req, Exception e) {
        log.error("未知异常!原因是:", e);
        return Result.error(ResultCodeEnum.UN_KNOW);
    }
}

到这里我们已经完成了Springboot捕获全局异常并以固定格式返回,接下来我们写个Controller测试一下。


六、测试

随便写个controller测试一下。

@RestController
@RequestMapping("/test")
public class TestController {

    //返回正确返回值
    @GetMapping("/testResult")
    public Result testResult() {
        //此处直接调用Result的静态方法,返回数据
        return Result.ok();
    }

    //测试空指针异常
    @GetMapping("/testNullPoint")
    public Result testNullPoint() {
        //故意抛出一个空指针,我们发现会被GlobalExceptionHandler捕获。
        NldDoctor doctor = null;
        String name = doctor.getName();
        return Result.ok();
    }

    //主动抛出自定义的异常
    @GetMapping("/testOtherException")
    public Result testOtherException() {
        //故意抛出异常
        int a = 10 / 0;
        return Result.ok();
    }

    //主动抛出自定义的异常
    @GetMapping("/throwBizException")
    public Result throwBizException() {
        //程序员根据业务需要,主要抛出BizException异常
        String name = "jack";
        if (name.equals("jack")) {
            throw new BizException(500, "出错了");
        }
        return Result.ok();
    }
}

调用Controller接口,我们会发现Controller控制器中,产生的异常都会被GlobalExceptionHandler类捕获,当没有异常时,我们可以调用Result工具类的各种静态方法,返回给前端期望的数据。以上便是本篇文章的全部内容,觉得有用的同学记得点赞哦!!!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小Y先生。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值