Springboot全局异常处理


为什么使用全局异常?

  • 在开发过程中,不管是 Dao、Servie、Controller,层都有可能发生异常,对于异常处理,通常是 try-catch 或者直接 throw,这会让 try-catch 的代码在代码中任意出现,系统的代码耦合度高,代码不美观,统一异常处理可以美化代码。

如何使用全局异常?

  • 在后端处理请求过程中发生了异常,DispatcherServlet 将异常处理委托给异常处理器(处理异常的类)。实现 HandlerExceptionResolver 接口的都是异常处理类。
  • 项目的异常一般集中处理,定义全局异常处理器。再结合框架提供的注解,诸如:@ExceptionHandler@ControllerAdvice@RestControllerAdvice 一起完成异常的处理。注意: 一定要和Controller中的注解(@Controller 和 RestController)保持一致性。
  • @ControllerAdvice@RestControllerAdvice 区别在于:@RestControllerAdvice 加了@RepsonseBody

一、不使用全局异常处理器

  • ① 编写控制器相关的代码,模拟出现了空指针异常。NullPointerException

    @RestController
    public class Controller {
    
        @GetMapping("/divide")
        public String divide(){
            String str = null;
            str.toString();
            return "success";
        }
    }
    
  • ② 发送请求返回结果查看。
    在这里插入图片描述


二、全局异常处理器

  • SpringBoot中,@ControllerAdvice 或 @RestControllerAdvice 即可开启全局异常处理,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用@ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。

1.自定义常量(返回状态码)

/**
 * 返回状态码的常量
 **/
public class StatusCodeConstant {
    public static final Integer ERROR = 500; //服务器非法错误
}

2.手动抛出异常

@RestController
public class Controller {
    @GetMapping("/divide")
    public String divide(){
        String str = null;
        str.toString();
        return "success";
    }
}

3.编写全局异常处理器

    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public String exceptionHandler(NullPointerException e){
        return "<h1>服务器出现错误,请联系管理员 ====> " + e.getMessage() + "</h1>";
    }

4.测试结果

在这里插入图片描述

  • 建议在参数签名中尽可能具体异常类,以减少异常类型和原因异常之间不匹配的问题,考虑创建多个@ExceptionHandler 方法的,每个方法通过其签名匹配单个特定的异常类型。最后增加一个根异常,考虑没有匹配的其他情况。

三、全局异常处理方式二

1.定义状态码常量

public class StatusCodeConstant {
    public static final Integer SUCCESS = 200;  //返回状态正常
    public static final Integer ERROR = 0; //返回错误
}

2. 定义基础接口(面向接口编程)

/**
 * 响应信息的基础接口
 **/
public interface ResponseResultBaseInfo {
    /**
     *  错误码
     */
    Integer getResultCode();

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

3.定义枚举类

/**
 * 异常处理枚举类
 */
public enum ResponseEnum implements ResponseResultBaseInfo{

    // 数据操作错误定义
    SUCCESS(200, "success"),
    ERROR(500,"error");

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

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

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

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

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

4.自定义数据传输对象

/**
 * 自定义数据传输对象
 */
@Data
public class ResponseResult {
    /**
     * 响应代码
     */
    private Integer code;

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

    /**
     * 响应结果
     */
    private Object result;
    public ResponseResult(){

    }

    public ResponseResult(ResponseResultBaseInfo res) {
        this.code = res.getResultCode();
        this.message = res.getResultMsg();
    }

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

    /**
     * 成功
     */
    public static ResponseResult success(Object data) {
        ResponseResult responseResult = new ResponseResult();
        responseResult.setCode(ResponseEnum.SUCCESS.getResultCode());
        responseResult.setMessage(ResponseEnum.SUCCESS.getResultMsg());
        responseResult.setResult(data);
        return responseResult;
    }

    /**
     * 失败
     */
    public static ResponseResult error(ResponseResultBaseInfo res) {
        ResponseResult responseResult = new ResponseResult();
        responseResult.setCode(res.getResultCode());
        responseResult.setMessage(res.getResultMsg());
        responseResult.setResult(null);
        return responseResult;
    }

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

    /**
     * 失败
     */
    public static ResponseResult error(String message) {
        ResponseResult responseResult = new ResponseResult();
        responseResult.setCode(StatusCodeConstant.ERROR);
        responseResult.setMessage(message);
        responseResult.setResult(null);
        return responseResult;
    }

}

5.定义全局异常处理器

/**
 * 全局异常处理器
 **/
@RestControllerAdvice 
public class ExceptionHandlerConfig {
    @ExceptionHandler(NullPointerException.class)
    public ResponseResult nullPointException(NullPointerException e) {
        return ResponseResult.error(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseResult exception() {
        return ResponseResult.error(ResponseEnum.ERROR);
    }
}

6.测试1

    @GetMapping("/latest")
    public ResponseResult getSensorDataLatest() {
        return ResponseResult.success("数据传输成功");
    }

在这里插入图片描述

7.测试2

    @GetMapping("/latest")
    public ResponseResult getSensorDataLatest() {
        int a = 1;
        if(a == 1)
            throw new ArithmeticException();
        return ResponseResult.success("数据传输成功");
    }

在这里插入图片描述


四、值得参考的博客


  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝945

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值