Элегантный глобальный метод обработки исключений проекта Spring Boot (последний во всей сети)

Spring Boot

предисловие

В повседневной разработке проектов исключения являются обычным явлением, но очень важно, как более эффективно обрабатывать информацию об исключениях, чтобы мы могли быстро обнаруживать ошибки, не только может повысить эффективность нашей разработки, но и сделать ваш код лучше. Удобный, проект SpringBoot уже обрабатывал некоторые исключения, но он может не подойти нам, разработчикам, поэтому нам нужно единообразно перехватывать и обрабатывать эти исключения.


1. Глобальный метод обработки исключений 1

В SpringBoot @ControllerAdvice может включить глобальную обработку исключений. Использование этой аннотации означает, что захват глобальных исключений включен. Нам нужно только аннотировать метод с помощью @ExceptionHandler и определить тип захваченного исключения, чтобы унифицировать эти захваченные исключения.

1.1 Настройка глобального класса исключений

/**
 * @description: 自定义异常处理
 * @author: DT
 * @date: 2021/4/19 21:17
 * @version: v1.0
 */
@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value =Exception.class)
    @ResponseBody
    public String exceptionHandler(Exception e){
        System.out.println("全局异常捕获>>>:"+e);
        return "全局异常捕获,错误原因>>>"+e.getMessage();
    }
}

1.2 Генерация исключений вручную

 @GetMapping("/getById/{userId}")
public CommonResult<User> getById(@PathVariable Integer userId){
    // 手动抛出异常
    int a = 10/0;
    return CommonResult.success(userService.getById(userId));
}

1.3 Тестовая печать

在这里插入图片描述 在这里插入图片描述

Очевидно, что такой эффект пользовательского опыта крайне слабый, хотя он может дать нам понять причину аномалии, во многих случаях он может быть недостаточно гуманным и не соответствовать нашим требованиям.

2. Глобальный метод обработки исключений 2

2.1 Определите базовый класс интерфейса

/**
 * @description: 服务接口类
 * @author: DT
 * @date: 2021/4/19 21:39
 */
public interface BaseErrorInfoInterface {

    /**
     *  错误码
     * @return
     */
    String getResultCode();

    /**
     * 错误描述
     * @return
     */
    String getResultMsg();
}

2.2 Определение класса перечисления

/**
 * @description: 异常处理枚举类
 * @author: DT
 * @date: 2021/4/19 21:41
 * @version: v1.0
 */
public enum ExceptionEnum implements BaseErrorInfoInterface{
    
    // 数据操作错误定义
    SUCCESS("2000", "成功!"),
    BODY_NOT_MATCH("4000","请求的数据格式不符!"),
    SIGNATURE_NOT_MATCH("4001","请求的数字签名不匹配!"),
    NOT_FOUND("4004", "未找到该资源!"),
    INTERNAL_SERVER_ERROR("5000", "服务器内部错误!"),
    SERVER_BUSY("5003","服务器正忙,请稍后再试!");

    /**
     * 错误码
     */
    private final String resultCode;

    /**
     * 错误描述
     */
    private final String resultMsg;

    ExceptionEnum(String resultCode, String resultMsg) {
        this.resultCode = resultCode;
        this.resultMsg = resultMsg;
    }

    @Override
    public String getResultCode() {
        return resultCode;
    }

    @Override
    public String getResultMsg() {
        return resultMsg;
    }
}

2.3 Пользовательский класс исключений

/**
 * @description: 自定义异常类
 * @author: DT
 * @date: 2021/4/19 21:44
 * @version: v1.0
 */
public class BizException extends RuntimeException{

    private static final long serialVersionUID = 1L;

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

    public BizException() {
        super();
    }

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

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

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

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

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


    public String getErrorCode() {
        return errorCode;
    }

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

    public String getErrorMsg() {
        return errorMsg;
    }

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

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

2.4 Пользовательская передача данных

/**
 * @description: 自定义数据传输
 * @author: DT
 * @date: 2021/4/19 21:47
 * @version: v1.0
 */
public class ResultResponse {
    /**
     * 响应代码
     */
    private String code;

    /**
     * 响应消息
     */
    private String message;

    /**
     * 响应结果
     */
    private Object result;

    public ResultResponse() {
    }

    public ResultResponse(BaseErrorInfoInterface errorInfo) {
        this.code = errorInfo.getResultCode();
        this.message = errorInfo.getResultMsg();
    }

    public String getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }

    /**
     * 成功
     *
     * @return
     */
    public static ResultResponse success() {
        return success(null);
    }

    /**
     * 成功
     * @param data
     * @return
     */
    public static ResultResponse success(Object data) {
        ResultResponse rb = new ResultResponse();
        rb.setCode(ExceptionEnum.SUCCESS.getResultCode());
        rb.setMessage(ExceptionEnum.SUCCESS.getResultMsg());
        rb.setResult(data);
        return rb;
    }

    /**
     * 失败
     */
    public static ResultResponse error(BaseErrorInfoInterface errorInfo) {
        ResultResponse rb = new ResultResponse();
        rb.setCode(errorInfo.getResultCode());
        rb.setMessage(errorInfo.getResultMsg());
        rb.setResult(null);
        return rb;
    }

    /**
     * 失败
     */
    public static ResultResponse error(String code, String message) {
        ResultResponse rb = new ResultResponse();
        rb.setCode(code);
        rb.setMessage(message);
        rb.setResult(null);
        return rb;
    }

    /**
     * 失败
     */
    public static ResultResponse error( String message) {
        ResultResponse rb = new ResultResponse();
        rb.setCode("-1");
        rb.setMessage(message);
        rb.setResult(null);
        return rb;
    }

    @Override
    public String toString() {
        return JSONObject.toJSONString(this);
    }

}

2.5 Настройка глобальной обработки исключений

/**
 * @description: 自定义异常处理
 * @author: DT
 * @date: 2021/4/19 21:51
 * @version: v1.0
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 处理自定义的业务异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public ResultResponse bizExceptionHandler(HttpServletRequest req, BizException e){
        logger.error("发生业务异常!原因是:{}",e.getErrorMsg());
        return ResultResponse.error(e.getErrorCode(),e.getErrorMsg());
    }

    /**
     * 处理空指针的异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseBody
    public ResultResponse exceptionHandler(HttpServletRequest req, NullPointerException e){
        logger.error("发生空指针异常!原因是:",e);
        return ResultResponse.error(ExceptionEnum.BODY_NOT_MATCH);
    }

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

2.6 Тестовый код

@PostMapping("/add")
public boolean add(@RequestBody User user) {
    //如果姓名为空就手动抛出一个自定义的异常!
    if(user.getName()==null){
        throw  new BizException("-1","用户姓名不能为空!");
    }
    return true;
}

在这里插入图片描述

 @PutMapping("/update")
public boolean update(@RequestBody User user) {
    //这里故意造成一个空指针的异常,并且不进行处理
    String str = null;
    str.equals("111");
    return true;
}

在这里插入图片描述

 @DeleteMapping("/delete")
public boolean delete(@RequestBody User user)  {
    //这里故意造成一个异常,并且不进行处理
    Integer.parseInt("abc123");
    return true;
}

在这里插入图片描述Если мы хотим поймать это исключение преобразования типа, можем ли мы просто добавить устаревший метод обработчика.在这里插入图片描述

/**
* 处理类型转换异常
 * @param req
 * @param e
 * @return
 */
@ExceptionHandler(value = NumberFormatException.class)
@ResponseBody
public ResultResponse exceptionHandler(HttpServletRequest req, NumberFormatException e){
    logger.error("发生类型转换异常!原因是:",e);
    return ResultResponse.error(ExceptionEnum.PARAMS_NOT_CONVERT);
}
PARAMS_NOT_CONVERT("4002","类型转换不对!"),

在这里插入图片描述

В дополнение к вышеуказанным форматам данных пользовательская глобальная обработка исключений также может обрабатывать переходы на страницы.Просто заполните путь перехода в обработке возврата недавно добавленного метода исключения и не используйте аннотацию ResponseBody.

Суммировать

Обработка исключений может уменьшить повторение и сложность кода, что способствует его обслуживанию, и может быстро обнаруживать ошибки, что значительно повышает эффективность нашей разработки.