您的位置:首页 > 编程语言 > Java开发

Springboot项目统一异常处理

2019-06-21 12:49 507 查看

Springboot项目统一异常处理

  • 二.定义全局异常类
  • 三.定义异常处理类
  • 四.特殊处理404异常
  • 五.测试使用效果
  • 一.接口返回值封装

    基于目前大多数项目都采用前后端分离架构,所以后端接口统一返回值封装是比较重要的,便于前后端对接与统一处理。当然按各自项目约定实现即可,思路大同小异,下面是我的实现方式,仅供参考

    1. 定义Result对象,作为通用返回结果封装

    /**
    * <p>@filename Result</p>
    * <p>
    * <p>@description 通用返回结果封装</p>
    *
    * @author llspace
    * @version 1.0
    * @since 2019/6/17 11:55
    **/
    @Data
    public class Result<T> {
    private int code;
    private String msg;
    private T data;
    /**
    * 成功时候的调用
    */
    public static <T> Result<T> success(T data) {
    return new Result<T>(data);
    }
    /**
    * 失败时候的调用
    */
    public static <T> Result<T> error(CodeMsg cm) {
    return new Result<T>(cm);
    }
    private Result(T data) {
    this.code = 0;
    this.msg = "success";
    this.data = data;
    }
    private Result(CodeMsg cm) {
    if (cm == null) {
    return;
    }
    this.code = cm.getCode();
    this.msg = cm.getMsg();
    }
    }

    2. 定义CodeMsg对象,作为通用状态码和消息封装

    /**
    * <p>@filename CodeMsg</p>
    * <p>
    * <p>@description 通用状态码和消息封装</p>
    *
    * @author llspace
    * @version 1.0
    * @since 2019/6/17 11:57
    **/
    @Data
    public class CodeMsg {
    //自定义状态码
    private int code;
    //消息信息
    private String msg;
    //通用异常 4001XX
    public static CodeMsg SUCCESS = new CodeMsg(0, "success");
    public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务端异常");
    //模块1 4002XX
    //模块2 4003XX
    //模块3 4004XX
    private CodeMsg(int code, String msg) {
    this.code = code;
    this.msg = msg;
    }
    public CodeMsg fillArgs(Object... args) {
    int code = this.code;
    String message = String.format(this.msg, args);
    return new CodeMsg(code, message);
    }
    }

    二.定义全局异常类

    基于上面封装的CodeMsg实现GlobalException定义,异常继承RuntimeException

    /**
    * <p>@filename GlobalException</p>
    * <p>
    * <p>@description 全局异常信息</p>
    *
    * @author llspace
    * @version 1.0
    * @since 2019/6/20 18:05
    **/
    @Data
    public class GlobalException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    private CodeMsg codeMsg;
    public GlobalException(CodeMsg codeMsg) {
    super(codeMsg.toString());
    this.codeMsg = codeMsg;
    }
    }

    三.定义异常处理类

    @RestControllerAdvice作用等同于@ResponseBody加上@ControllerAdvice,会在所有带有@Controller或者@RestController注解的类上生效,还可以使用basePackages参数配置指定异常处理类生效的包

    /**
    * <p>@filename GlobalExceptionHandler</p>
    * <p>
    * <p>@description 全局异常处理类</p>
    *
    * @author llspace
    * @version 1.0
    * @since 2019/6/20 18:07
    **/
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
    e.printStackTrace();
    if(e instanceof GlobalException) {
    GlobalException exception = (GlobalException) e;
    return Result.error(exception.getCodeMsg());
    }else if(e instanceof BindException) {
    BindException ex = (BindException) e;
    List<ObjectError> errors = ex.getAllErrors();
    ObjectError error = errors.get(0);
    String msg = error.getDefaultMessage();
    return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
    }else {
    return Result.error(CodeMsg.SERVER_ERROR);
    }
    }
    }

    四.特殊处理404异常

    spring boot默认不会抛出404异常(NoHandlerFoundException),所以在ControllerAdvice中捕获不到该异常,导致404总是跳过ContollerAdvice,直接显示ErrorController的错误页。需要改变配置,让404错误抛出异常(NoHandlerFoundException),这样便可在ControllerAdvice中捕获此异常。

    如果是restful项目改变配置即可实现捕获上述异常,在application.yml中添加:

    spring:
    mvc:
    throw-exception-if-no-handler-found: true
    resources:
    add-mappings: false

    注意:添加了如上配置会造成项目静态资源访问异常, 如果不是restful的项目这样配置就会有问题,所以就需要采用其他方式来处理了, 可以参考如下处理方法

    如果是带静态资源的项目我们要如何来处理404异常呢?

    断点下BasicErrorController类,查看下源码可知,errorHtml()方法默认会返回一个new ModelAndView(“error”, model),所以其实在classpath:/templates下自定义一个error.html即可,这样springboot默认的404错误就跳转到了自己项目下的error页面了,这种处理比较简单,如果想更好的封装错误页面,建议自己实现ErrorController接口,或者继承AbstractErrorController / BasicErrorController类来实现,当然前提是删除掉配置文件中上述的两个配置

    五.测试使用效果

    至此,统一异常处理就实现了,如下使用,

    if(loginVO == null) {
    throw new GlobalException(CodeMsg.SERVER_ERROR);
    }

    这样会抛出异常如下:

    GlobalException(codeMsg=CodeMsg(code=500100, msg=服务端异常))

    如果是404异常会跳项目自定义的error页面

    个人实现,仅供参考,有兴趣的小伙伴自己动手尝试吧!

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: