SpringBoot之统一异常处理

前言:

平时做项目时,在Controller层只会返回一个JSON串来表示信息是否成功~还真的没有考虑到异常是怎么处理的,不过肯定是统一管理异常。

一、全局错误页面:

         Spring Boot提供了一个默认的映射:/error(当然该页面并不友好),当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容。

  • 创建全局异常处理类:通过使用@ControllerAdvice定义统一的异常处理类,而不是在每个Controller中逐个定义。@ExceptionHandler用来定义函数针对的异常类型,最后将Exception对象和请求URL映射到error.html中。
  • 实现error.html页面展示:在templates目录下创建error.html,将请求的URL和Exception对象的message输出。
@ControllerAdvice
class GlobalExceptionHandler {

    public static final String DEFAULT_ERROR_VIEW = "error";

    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", req.getRequestURL());
        mav.setViewName(DEFAULT_ERROR_VIEW);
        return mav;
    }

}
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>统一异常处理</title>
</head>
<body>
    <h1>Error Handler</h1>
    <div th:text="${url}"></div>
    <div th:text="${exception.message}"></div>
</body>

       我们只需要在Controller中抛出Exception,当然我们可能会有多种不同的Exception。然后在@ControllerAdvice类中,根据抛出的具体Exception类型匹配@ExceptionHandler中配置的异常类型来匹配错误映射和处理。

二、返回JSON格式

    通过@ControllerAdvice统一定义不同Exception映射到不同错误处理页面。而当我们要实现RESTful API时,返回的错误是JSON格式的数据,而不是HTML页面。

    本质上,只需在@ExceptionHandler之后加入@ResponseBody,就能让处理函数return的内容转换为JSON格式。

  • 创建统一的JSON返回对象
code:消息类型,msg:提示消息,data 具体内容
public class Result<T> {

    /** 错误码. */
    private Integer code;

    /** 提示信息. */
    private String msg;

    /** 具体的内容. */
    private T data;

    //getter setter方法
}
  • 出现异常信息
比如查询一个学生年龄,规定小于10 的话是上小学,大于10小于16是在上初中~
public void getAge(Integer id){
    Student stu = Stu.finOne(id);
    Integer age = stu.getAge();
    if(age < 10){
        throw new Exception("你在上小学吧");
    }else if(age > 10 && age < 16){
        throw new Exception("你可能在上初中");
    }
}

不符合规范的处理方式

    1. 既然要返回Json串那么就要把消息类型与信息给加进去~      自定义异常

    2. 没有一个统一的地方来维护。

public class StuException extends RuntimeException{   //继承这个才会回滚, 否则继承Exception不会回滚

    private Integer code;

    public StuException(ResultEnum resultEnum) {
        super(resultEnum.getMsg());
        this.code = resultEnum.getCode();
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}
  • 统一异常处理:
ControllerAdvice
public class ExceptionHandle {

    private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e) {
        if (e instanceof StuException) {
            StuException stuException = (StuException) e;
            return ResultUtil.error(stuException.getCode(), stuException.getMessage());
        }else {
            logger.error("【系统异常】{}", e);
            return ResultUtil.error(-1, "未知错误");
        }
    }
}
  • 枚举来统一管理: 

枚举一般都是用构造方法来创建,提供get方法。

public enum ResultEnum {
    UNKONW_ERROR(-1, "未知错误"),
    SUCCESS(0, "成功"),
    PRIMARY_SCHOOL(100, "我猜你可能还在上小学"),
    MIDDLE_SCHOOL(101, "你可能在上初中"),
    ;

    private Integer code;

    private String msg;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}
  • 符合规范的调用方式:
public void getAge(Integer id){
    Student stu = Stu.finOne(id);
    Integer age = stu.getAge();
    if(age < 10){
        throw new StuException(ResultEnum.PRIMARY_SCHOOL));
    }else if(age > 10 && age < 16){
        throw new StuException(ResultEnum.MIDDLE_SCHOOL);
    }
}

总结:

这样的优点在于抛出自己定义的异常统一处理,用枚举形式来统一管理,即错误小本本,错误码能对应到错误信息的~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值