我是靠谱客的博主 懦弱纸飞机,最近开发中收集的这篇文章主要介绍SpringBoot 全局异常拦截捕获处理1、需求2、实现方式3、具体步骤,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

个人学习用-搬运原文链接

1、需求

前后端分离项目中,后端通常是以json形式将数据返回给前端。此时,如果服务器内部出现异常,如何对内部异常处理后响应给前端呢?

2、实现方式

结合 @RestControllerAdvice@ExceptionHandler 来捕获绝大部分异常,然后通过自定义的全局数据返回对象统一返回Json形式给前端。
@RestControllerAdvice: 增强类;
@ExceptionHandler: 标注异常处理方法,包括异常类型。

3、具体步骤

3.1、自定义 全局数据返回对象

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;

/**
 * 接口返回数据格式
 */
@Data
@ApiModel(value = "接口返回对象", description = "接口返回对象")
public class Result<T> implements Serializable {
  /**
   * 状态码
   */
  private static final Integer HANDLE_OK = 200;
  private static final Integer CLIENT_NOT_FOUND_404 = 404;
  private static final Integer CLIENT_NO_AUTH_401 = 401;
  private static final Integer SERVER_ERROR_500 = 500;
  private static final Integer SERVER_NO_AUTH_510 = 200;

  private static final long serialVersionUID = 1L;

  /**
   * 成功标志
   */
  @ApiModelProperty(value = "成功标志")
  private boolean success = true;

  /**
   * 返回处理消息
   */
  @ApiModelProperty(value = "返回处理消息")
  private String message = "";

  /**
   * 返回代码(状态码)
   */
  @ApiModelProperty(value = "返回代码")
  private Integer code = 0;

  /**
   * 返回数据对象 data
   */
  @ApiModelProperty(value = "返回数据对象")
  private T result;

  /**
   * 时间戳
   */
  @ApiModelProperty(value = "时间戳")
  private long timestamp = System.currentTimeMillis();

  public Result() {
  }

  /**
   * 兼容VUE3版token失效不跳转登录页面
   * @param code
   * @param message
   */
  public Result(Integer code, String message) {
    this.code = code;
    this.message = message;
  }

  public Result<T> success(String message) {
    this.message = message;
    this.code = HANDLE_OK;
    this.success = true;
    return this;
  }

  public static <T> Result<T> ok() {
    Result<T> r = new Result<T>();
    r.setSuccess(true);
    r.setCode(HANDLE_OK);
    return r;
  }

  public static <T> Result<T> ok(String msg) {
    Result<T> r = new Result<T>();
    r.setSuccess(true);
    r.setCode(HANDLE_OK);
    r.setMessage(msg);
    r.setResult((T) msg);
    return r;
  }

  public static <T> Result<T> ok(T data) {
    Result<T> r = new Result<T>();
    r.setSuccess(true);
    r.setCode(HANDLE_OK);
    r.setResult(data);
    return r;
  }

  public static <T> Result<T> ok(String msg, T data) {
    Result<T> r = new Result<T>();
    r.setSuccess(true);
    r.setCode(HANDLE_OK);
    r.setMessage(msg);
    r.setResult(data);
    return r;
  }

  public static <T> Result<T> error(String msg) {
    return error(SERVER_ERROR_500, msg);
  }
  
  public static <T> Result<T> error(String msg, T data) {
    Result<T> r = new Result<T>();
    r.setSuccess(false);
    r.setCode(SERVER_ERROR_500);
    r.setMessage(msg);
    r.setResult(data);
    return r;
  }

  public static <T> Result<T> error(int code, String msg) {
    Result<T> r = new Result<T>();
    r.setCode(code);
    r.setMessage(msg);
    r.setSuccess(false);
    return r;
  }

  public Result<T> error500(String message) {
    this.message = message;
    this.code = SERVER_ERROR_500;
    this.success = false;
    return this;
  }

  /**
   * 无权限访问返回结果
   */
  public static <T> Result<T> noauth(String msg) {
    return error(SERVER_NO_AUTH_510, msg);
  }
}

3.2、自定义 全局异常捕获处理类

1. 清楚具体异常类型时

在类上,通过 @RestControllerAdvice(annotations = Controller.class) 注解标注全局异常处理类,指定处理带有@Controller注解的类,也就是controller层的所有方法。
在方法上,通过 @ExceptionHandler({ArithmeticException.class}) 标注异常处理方法以及方法所处理的异常类型。

@Slf4j
@RestControllerAdvice
public class ExceptionsHandler {

    @ExceptionHandler({ArithmeticException.class})
    public Result<String> arithmeticException(ArithmeticException ex) {
        log.error("除数不能为0:{} ", ex.getMessage(), ex);
        return Result.error(400, "除数不能为0");
    }
}

2. 不清楚具体异常类型时,直接捕获异常的公共类 Exception

@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);

    @ExceptionHandler(Exception.class)
    public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 打印异常日志
        logger.error(e.getMessage());
        StackTraceElement[] stackTrace = e.getStackTrace();
        for (StackTraceElement element : stackTrace) {
            logger.error(element.toString());
        }

        // 返回处理结果,要判断异常发生的请求是普通请求(返回页面),还是异步请求(返回json数据)
        String xRequestedWith = request.getHeader("x-requested-with");
        // 异步请求
        if (xRequestedWith.equals("XMLHttpRequest")) {
            response.setContentType("application/plain;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write(CommunityUtil.getJSONString(1, "服务器发生异常!"));
        } else {
            response.sendRedirect(request.getContextPath() + "/error");
        }
    }
}

3.3、编写测试方法

编写测试方法(会出现异常的方法)

@RestController
@RequestMapping("/exception")
public class ExceptionTestController {

    @GetMapping("/test")
    public Result<Integer> testException(int num) {
        int res = 23 / num;
        return Result.ok(res);
    }
}

3.4、测试

异步请求: 返回json数据
在这里插入图片描述
普通方法: 返回页面
在这里插入图片描述

最后

以上就是懦弱纸飞机为你收集整理的SpringBoot 全局异常拦截捕获处理1、需求2、实现方式3、具体步骤的全部内容,希望文章能够帮你解决SpringBoot 全局异常拦截捕获处理1、需求2、实现方式3、具体步骤所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部