基于SpringBoot的全局异常处理

目录

1、CommonReturnType.class

2、CommonError接口

3、BusinessException.class

4、枚举类EnuBusinessError 

5、BusinessExceptionHandle.class


本篇介绍后端Controller层如何返回统一的数据格式给前端。

因为涉及到异常的处理,所以制作了一个java异常的简略图,如下:

首先定义一个全局返回的类,该类定义了返回给前端的统一格式:状态码+返回数据,具体代码实现如下:

1、CommonReturnType.class

public class CommonReturnType {

    /**
     * 返回数据
     */
    private String status;

    /**
     * 返回状态码
     */
    private Object data;

    public static CommonReturnType create(String status,Object data){
        CommonReturnType type = new CommonReturnType();
        type.setStatus(status);
        type.setData(data);
        return type;
    }

    public static CommonReturnType create(Object data){
        return CommonReturnType.create("success",data);
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

以上全局返回参数只适应于程序没有错误和异常的情况,所以针对错误和异常,我们需要另外再定义其他类来实现,首先定义一个公共错误的接口,接口中需要有获取错误码(errorCode)和错误信息(errorMessage)的方法,另外还需要设计一个设置错误信息的方法,以便我们能自定义异常,代码实现如下:

2、CommonError接口

public interface CommonError {

    public Integer getErrorCode();

    public String getErrorMsg();

    public CommonError setErrorMsg(String errorMsg);

}

然后对于异常的处理,我们需要定义自己能够及时判断错误的信息,准确的明确和找到程序错误,因此我们需要自定义自己的异常类,代码如下:

3、BusinessException.class

public class BusinessException extends RuntimeException implements CommonError{

    private CommonError commonError;

    public BusinessException(CommonError commonError){
        super();
        this.commonError = commonError;
    }

    public BusinessException(CommonError commonError,String errorMsg){
        super();
        this.commonError = commonError;
        // 对errorMsg进行二次修改
        this.commonError.setErrorMsg(errorMsg);
    }

    @Override
    public Integer getErrorCode() {
        return this.commonError.getErrorCode();
    }

    @Override
    public String getErrorMsg() {
        return this.commonError.getErrorMsg();
    }

    @Override
    public CommonError setErrorMsg(String errorMsg) {
        this.commonError.setErrorMsg(errorMsg);
        return this;
    }
}

对于错误信息,随着程序代码的不断增加,我们希望能够把错误信息进行归类整理,以便后期能够方便进行维护和拓展,因此,我们使用枚举类来进行定义,定义格式跟公共错误接口的格式保持一致:错误码+错误信息;代码实现如下:

4、枚举类EnuBusinessError 

public enum EnuBusinessError implements CommonError{

    // 定义一个通用错误类型
    PARAMETER_VILIDATION_ERROR(10000,"参数不合法"),

    // 定义未知错误
    NUKNOW_ERROR(10002,"未知错误"),

    ;

    private Integer errorCode;

    private String errorMsg;

    private EnuBusinessError(Integer errorCode,String errorMsg){
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    };

    @Override
    public Integer getErrorCode() {
        return this.errorCode;
    }

    @Override
    public String getErrorMsg() {
        return this.errorMsg;
    }

    @Override
    public CommonError setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
        return this;
    }
}

最后,也是最关键的一步,我们要成功捕获控制层(Controller)程序中的异常信息,并把异常信息转化为我们自己定义的信息,我们需要借助Spring中的相关注解

@ControllerAdvice 控制器增强,被该注解标记的类可以作用于全局的Controller上

@ExceptionHandler Controller层异常处理和捕获

5、BusinessExceptionHandle.class

@ControllerAdvice //使用该注解捕获全局异常
public class BusinessExceptionHandle {
    
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)// 自定义异常响应对应的状态码,碰到了某个自定义异常加上了@ResponseStatus,
                                  // 就继续抛出,这样就不会让自定义异常失去加上@ResponseStatus的初衷
    public CommonReturnType BusinessExceptionHandle(Exception e){
        Map<String,Object> resultMap = new HashMap<>();
        if(e instanceof BusinessException){
            BusinessException ex = (BusinessException) e;
            resultMap.put("errorCode",ex.getErrorCode());
            resultMap.put("errorMsg",ex.getErrorMsg());
        }else{
            resultMap.put("errorCode",EnuBusinessError.NUKNOW_ERROR.getErrorCode());
            resultMap.put("errorMsg",EnuBusinessError.NUKNOW_ERROR.getErrorMsg());
        }
        return CommonReturnType.create(resultMap);
    }
}

综合上述,代码使用效果如下图所示:

补充实例代码

import com.x.x.common.core.constant.CommonConstants;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;

import java.io.Serializable;


/**
 * 响应信息主体
 */
@Builder // 自动生成 builder() 方法,并且直接根据字段名称方法进行字段赋值,最后使用 build()方法构建出一个实体对象。
@ToString // 给类自动生成 toString 方法,带上有所非静态字段的属性名称和值
@NoArgsConstructor // 为实体类生成无参的构造器方法
@AllArgsConstructor // 为实体类生成除了static修饰的字段之外带有各参数的构造器方法
@Accessors(chain = true) // 每次使用set方法返回的都是对象本身
@ApiModel(value = "响应信息主体")
public class CommonResponse<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	@Getter // 生成getter方法
	@Setter // 生成setter方法
	@ApiModelProperty(value = "返回标记:成功标记=0,失败标记=1")
	private int code;

	@Getter
	@Setter
	@ApiModelProperty(value = "返回信息")
	private String msg;

	@Getter
	@Setter
	@ApiModelProperty(value = "数据")
	private T data;

	public static <T> CommonResponse<T> ok() {
		return restResult(null, CommonConstants.SUCCESS, null);
	}

	public static <T> CommonResponse<T> ok(T data) {
		return restResult(data, CommonConstants.SUCCESS, null);
	}

	public static <T> CommonResponse<T> ok(T data, String msg) {
		return restResult(data, CommonConstants.SUCCESS, msg);
	}

	public static <T> CommonResponse<T> failed() {
		return restResult(null, CommonConstants.FAIL, null);
	}

	public static <T> CommonResponse<T> failed(String msg) {
		return restResult(null, CommonConstants.FAIL, msg);
	}

	public static <T> CommonResponse<T> failed(T data) {
		return restResult(data, CommonConstants.FAIL, null);
	}

	public static <T> CommonResponse<T> failed(T data, String msg) {
		return restResult(data, CommonConstants.FAIL, msg);
	}

	private static <T> CommonResponse<T> restResult(T data, int code, String msg) {
		CommonResponse<T> apiResult = new CommonResponse<>();
		apiResult.setCode(code);
		apiResult.setData(data);
		apiResult.setMsg(msg);
		return apiResult;
	}

}

参考链接:实体类测试技巧:@Accessors注解的使用_QR_adaptor的博客-CSDN博客_accessors注解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

swadian2008

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

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

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

打赏作者

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

抵扣说明:

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

余额充值