欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot 全局异常处理

程序员文章站 2022-05-22 09:44:03
...

Spring boot全局异常处理

开发过程中难免会遇到异常处理,把异常信息进行封装,返回给用户能够理解的信息。但是异常这么多,我们不可能每个异常都能够完美处理,所以我们需要一个能够捕获到全局的异常,然后处理,以特定的格式返回给前端。spring boot就提供了@ControllerAdvice注解对异常进行全局捕获。

1、统一前端返回数据(JSON)

所有返回给前端的信息,都封装在ResponseData里面

public class ResponseData<T> implements Serializable {

    private static final long serialVersionUID = -3482839797434946211L;
    private int code;
    private String msg;
    private T data;

    ResponseData() {
    }

    ResponseData(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
2、定义常见的错误msg和code

这些错误信息都是不变的可以定义成一个枚举类型,里面包含code和msg

public enum ErrorCodeEnum {
    /**
     * 服务端错误
     */
    SERVER_ERROR(1000, "服务端错误"),
    /**
     * 参数错误
     */
    SERVER_ERROR_PARAM(2000, "参数错误"),
    /**
     * 业务异常
     */
    BUSINESS_ERROR(3000, "业务异常"),

    /**
     * 网络异常
     */
    NETWORK_ERROR(4000, "网络异常");

    private String msg;
    private int code;

    ErrorCodeEnum(int code, String msg) {
        this.msg = msg;
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public int getCode() {
        return code;
    }
}
3、定义业务异常相关

业务异常有很多,这里我使用统一的业务异常BusinessException其他的业务异常可以继承统一业务异常

public class BusinessException extends RuntimeException {

    private static final long serialVersionUID = 2066878262694332718L;
    private ErrorCodeEnum errorCode;
    private String msg;

    public BusinessException(ErrorCodeEnum code, Throwable cause) {
        super(code.getMsg(), cause);
        this.errorCode = code;
    }

    public BusinessException(ErrorCodeEnum code, String cause) {
        super(cause);
        this.errorCode = code;
        this.msg = cause;
    }

    public BusinessException(ErrorCodeEnum code) {
        this.errorCode = code;
        this.msg = code.getMsg();
    }

    public ErrorCodeEnum getErrorCode() {
        return errorCode;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
4、定义全局异常捕获
@ControllerAdvice
@Slf4j
public class DefaultExceptionHandler {

    @ExceptionHandler(value = IllegalArgumentException.class)
    @ResponseBody
    public ResponseData handlerError(HttpServletRequest req, IllegalArgumentException ex) {
        log.warn("非法参数,path:{},param:{}", req.getRequestURI(), req.getQueryString(), ex);
        return handleErrorInfo(ErrorCodeEnum.SERVER_ERROR_PARAM.getMsg(), ErrorCodeEnum.SERVER_ERROR_PARAM.getCode());
    }

    @ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public ResponseData handlerError(HttpServletRequest req, BusinessException ex) {
        log.warn("BusinessException,path:{},param:{}", req.getRequestURI(), req.getQueryString(), ex);
        return handleErrorInfo(ex.getMsg(), ex.getErrorCode().getCode());
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseData handlerError(HttpServletRequest req, Exception ex) {
        log.warn("exception! path:{},param:{}", req.getRequestURI(), req.getQueryString(), ex);
        return handleErrorInfo(ErrorCodeEnum.SERVER_ERROR.getMsg(), ErrorCodeEnum.SERVER_ERROR.getCode());
    }

    private ResponseData<String> handleErrorInfo(String msg, int code) {
        ResponseData<String> responseData = new ResponseData<>();
        responseData.setCode(code);
        responseData.setMsg(msg);
        responseData.setData(msg);
        return responseData;
    }
}
5、测试Controller
@RestController
public class TestController {

    @GetMapping("/test")
    public ResponseData test(String exceptionInfo){
        if ("参数错误".equals(exceptionInfo)) {
            throw new IllegalArgumentException();
        }
        if ("业务异常".equals(exceptionInfo)){
            throw new BusinessException(ErrorCodeEnum.BUSINESS_ERROR);
        }
        if ("其他异常".equals(exceptionInfo)){
            throw new RuntimeException();
        }

        ResponseData<String> responseData = new ResponseData<>();
        responseData.setData("没有异常");
        responseData.setCode(0);
        responseData.setMsg("没有异常");
        return responseData;
    }
}
6、postman测试

Spring Boot 全局异常处理
Spring Boot 全局异常处理