优雅的异常处理机制

Posted by zjh on September 29, 2020

优雅的异常处理机制

1、 在web系统开发过程中,前后端分离架构模式下,后台的逻辑判断和异常处理(例如非空验证,长度验证等等)直接抛给前端总是一个比较痛苦的事情,可能需要前端对后端返回的某一个值进行判断,再进行异常的输出。 这种模式下,如果判断信息太多,接口的出参DTO数据结构还需要不断地重新构建,拓展性十分差劲。

2、如果能够以全局的形式处理,后端有逻辑判断只抛异常,前端对于httpStatus进行判断(500时自动走异常分支),这样一来,前端不需要做频繁的参数校验,后端也不需要对接口结构进行不断调整,这样的架构,是每个程序员乐于接受的。

3、先上图看效果

后端进行逻辑判断时,只需要这样抛出异常,全局异常处理器会相应返回固定的数据格式

前端接收是只需要在异常catch或者判断HttpStatus的范围即可进行异常拦截,减少了大量的代码

定义优雅的全局自定义系统异常类

BlogSystemException.java 定义自定义的异常类

最好是继承自RuntimeException ,不然会在编译期,需要你手动在方法上抛出

/**
 * @Describe: 主动抛出的异常,用于控制器处理
 * @Author: zjhChester
 * @Date: 14:47 2020/9/29
 */
public class BlogSystemException extends RuntimeException {
    public BlogSystemException() {
        super();
    }

    public BlogSystemException(String message) {
        super("系统出现异常:"+message);
    }

    public BlogSystemException(String message, Throwable cause) {
        super(message, cause);
    }

    public BlogSystemException(Throwable cause) {
        super(cause);
    }

    protected BlogSystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

SystemExceptionHandler.java 异常处理器

通过ResponseEntity 将封装的所有信息当成异常处理的自定义结构抛出


import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import xyz.zjhwork.conf.exception.BlogSystemException;
import xyz.zjhwork.resmodel.ResponseModel;

import java.util.Objects;

/**
 * @Describe: 处理系统自定义总线异常的处理
 * @Author: zjhChester
 * @Date: 14:54 2020/9/29
 */
@Slf4j
@Component
@ControllerAdvice
public class SystemExceptionHandler {
    @ResponseBody
    @ExceptionHandler({BlogSystemException.class})
//此处的入参只需要写自定义异常类的父类即
    public ResponseEntity<ResponseModel> handleValidException(RuntimeException e) {
        //日志记录错误信息
        log.error(Objects.requireNonNull(e.getMessage()));
        //将错误信息返回给前台
        return ResponseEntity.status(500).body( ResponseModel.failResModel(99999999,Objects.requireNonNull(e.getMessage()), e.getStackTrace()));
    }
}

测试

@GetMapping("/{id}")
    public ResponseModel get(@PathVariable("id") Integer id){
        throw new BlogSystemException("测试主动抛出异常2");
    }

结果