02.25 2020教你如何对SpringBoot进行优雅的全局异常处理

在项目中经常出现系统异常的情况,比如NullPointerException等等。如果默认未处理的情况下,springboot会响应默认的错误提示,这样对用户体验不是友好,系统层面的错误,用户不能感知到,即使为500的错误,可以给用户提示一个类似服务器开小差的友好提示等。这时候便可以使用全局异常处理器来优雅的处理全局异常


定义错误消息类

  • 在全局异常类中会使用该错误消息进行初始化
  • 注意该消息的toString方法要写成Json格式的
  • 具体的错误消息初始化的时候也可以使用%s一类的占位符,后期调用静态方法,来填充多个参数
  • 这里使用了@Data注解省去了自己编写构造函数,详情可以查找lombook使用方法
  • <code>@Data@AllArgsConstructor@Slf4jpublic class CodeMsg implements Serializable {    private int code;    private String msg;    public static CodeMsg SUCCESS = new CodeMsg(200, "success");    public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务器错误");    public static CodeMsg INSERT_ERROR = new CodeMsg(500200, "插入错误");    public static CodeMsg UNKNOWN_ERROR = new CodeMsg(-999, "未知错误:%s");    //填充多个错误信息    public static CodeMsg BIND_ERROR = new CodeMsg(500300,"参数校验异常:%s");    public static CodeMsg UNSELECT_FILE_ERROR = new CodeMsg(500400,"未选择文件");    public static CodeMsg FILE_NOT_EXIST_ERROR = new CodeMsg(500500, "文件或文件夹不存在");    public static CodeMsg UPLOADING = new CodeMsg(500600, "正在上传");    //补充未知错误的具体信息    public CodeMsg fillArgs(Object... args){        int code =  this.code;        String message = String.format(this.msg,args);        return new CodeMsg(code,message);    }    //处理异常时返回json的toString    @Override    public String toString() {        return "CodeMsg{" +                "code=" + code +                ", msg='" + msg + '\\'' +                '}';    }    // public static void main(String[] args) {    //     log.info(new CodeMsg(0, "hello").toString());    // }}/<code>

    定义全局异常类

  • 之后遇到什么错误,可以用错误消息类初始化全局异常类,并抛出该异常,该异常之后会被全局异常处理器捕获
  • <code>//继承RuntimeException,并定义serialVersionUIDpublic class GlobalException extends RuntimeException {    private static final long serialVersionUID = -3586828184536704147L;    private CodeMsg codeMsg;    public GlobalException(CodeMsg codeMsg) {        super(codeMsg.toString());        this.codeMsg = codeMsg;    }    public CodeMsg getCodeMsg() {        return codeMsg;    }}/<code>

    定义返回结果类

  • 返回结果有两种,一种是返回相应的错误码,一种是返回正确的验证码+数据,因此我们编写返回结果类
  • <code>@Data@ApiModel(description = "返回结果")public class Result implements Serializable {    private int code;    private T data;    private String msg;    private Result(T data) {        this.code = 0;        this.msg = "success";        this.data = data;    }    private Result() {        this.code = 0;        this.msg = "success";        this.data = null;    }    private Result(CodeMsg codeMsg) {        if (codeMsg == null) {            return;        }        this.code = codeMsg.getCode();        this.msg = codeMsg.getMsg();    }    public static  Result success(T data) {        return new Result(data);    }    public static  Result success() {        return new Result();    }    public static  Result error(CodeMsg codeMsg) {        return new Result(codeMsg);    }}/<code>

    定义全局异常处理器

    • 使用@ControllerAdvice来指定全局异常处理
    • 使用@RestController返回json数据
    • 使用@ExceptionHandler来捕获特定的异常种类
    <code>@ControllerAdvice@RestController@Slf4jpublic class GlobalExceptionHandler {    //自定义异常类    @ExceptionHandler(value = GlobalException.class)    public Result<string> globalExceptionHandler(HttpServletRequest request, GlobalException e) {        log.error(e.getCodeMsg().getMsg());        return Result.error(e.getCodeMsg());    }    //参数检测不合格    @ExceptionHandler(value = MethodArgumentNotValidException.class)    public Result<string> bindExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e) {        log.error(e.getClass().toString());        // log.error(e.toString());        List<objecterror> errors = e.getBindingResult().getAllErrors();        StringBuilder errorMsg = new StringBuilder();        //此处仅取第一个        // ObjectError objectError = errors.get(0);        for (ObjectError error : errors) {            errorMsg.append(error.getDefaultMessage()).append(" ");        }        // String errorMsg = objectError.getDefaultMessage();        //填充具体异常        return Result.error(CodeMsg.BIND_ERROR.fillArgs(errorMsg.toString()));    }    //其他异常类    @ExceptionHandler(value = Exception.class)    public Result<string> defaultExceptionHandler(HttpServletRequest request, Exception e) {        log.error(e.getClass().toString());        log.error(e.toString());        e.printStackTrace();        return Result.error(CodeMsg.UNKNOWN_ERROR.fillArgs(e.getClass().toString()));    }    //可定义详细的其他异常类    // @ExceptionHandler(AuthenticationException.class)   //此处为shiro未登录异常类    // @ResponseStatus(HttpStatus.UNAUTHORIZED)    // public String unAuth(AuthenticationException e) {    //     log.error("用户未登陆:", e);    //     return "/login.html";    // }}/<string>/<objecterror>/<string>/<string>/<code>

    效果

    至此,便完成了自定义的全局异常处理方法,访问效果如下

    <code> //成功 {    code = 0;    msg = "success";    data = 456; }  //失败 { code = 500100; msg = "服务器错误"; data = null; }/<code>

    以上内容都是我自己的一些感想,分享出来欢迎大家指正,顺便求一波关注,有需要的私信我哦


    2020教你如何对SpringBoot进行优雅的全局异常处理


    出处:https://juejin.im/post/5e54796af265da575d20dd5d


    分享到:


    相關文章: