简介

一、定义运行异常父类

二、定义异常响应对象和返回的Code状态码

三、定义全局异常类

四、使用全局异常类


简介

对全局运行异常处理进行封装,出现异常返回异常编码和自定义异常信息。

一、定义运行异常父类

以经常用的运行时异常RuntimeException为例

设计思想:

1、我们在定义自定义异常时,给前端发送异常的文本内容,但前端不通过文本判断

2、接口处理成功时不需要返回异常信息,前端接收到成功会自动跳转

3、返回的内容从对数据库影响的行数(例子)改为状态码和描述信息

import lombok.Getter;

public class ServiceException extends RuntimeException {
    /**
     * 状态码
     */
    @Getter
    private Integer state;

    public ServiceException(Integer state, String message) {
        super(message);
        this.state = state;
    }

}

二、定义异常响应对象和返回的Code状态码

import cn.tedu.csmall.product.ex.ServiceException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonResult implements Serializable {
    /**
     * 状态码
     */
    private Integer state;
    /**
     * 操作“失败”时的描述文本
     */
    private String message;
    public static JsonResult ok() {
        JsonResult jsonResult = new JsonResult();
        //ServiceCode.OK的这种写法是为了统一标准,且修改方便
        jsonResult.setState(ServiceCode.OK);
        return jsonResult;
    }
    /**
     *  重载的错误返回,返回自己错误的异常信息
     */
    public static JsonResult fail(ServiceException e) {
        return fail(e.getState(), e.getMessage());
    }
    /**
     *  重载的错误返回,不同的实现方式
     */
    public static JsonResult fail(Integer state, String message) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(state);
        jsonResult.setMessage(message);
        return jsonResult;
    }
}
public class ServiceCode {

    public static final Integer OK = 200;
    public static final Integer ERR_NOT_FOUND = 404;
    public static final Integer ERR_CONFLICT = 409;

}

三、定义全局异常类

import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.web.JsonResult;
import cn.tedu.csmall.product.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;

/**
 * 全局异常处理器
 */
@Slf4j//日志
@RestControllerAdvice //异常集合类
public class GlobalExceptionHandler {

    /**
     * 常见的运行时异常的响应信息
     */
    @ExceptionHandler
    public JsonResult handleServiceException(ServiceException e) {
        return JsonResult.fail(e);
    }
    /**
     * 在接收DTO对象但对象参数,属性不对时返回错误信息
     */
    @ExceptionHandler
    public JsonResult handleBindException(BindException e) {
        //第二种写法,其实直接传入e也行
        String message = e.getFieldError().getDefaultMessage();
        return JsonResult.fail(ServiceCode.ERR_CONFLICT, message);
    }
    /**
     *  异常的顶级父类异常,可以防止500错误,且将信息都能够输出到控制台中
     *  一般用于输出服务器错误,就是还没定的错误处理机制,但遇上了,就走这个异常处理方法
     */
    @ExceptionHandler
    public String handleThrowable(Throwable e) {
        String message = "服务器忙,请稍后再尝试,或联系系统管理员!(在开发过程中,看到此消息,应该检查出现异常的原因,并补充对此类异常的针对性的处理)";
        log.warn("程序执行过程中出现Throwable!");
        log.warn("异常类型:{}", e.getClass().getName());
        log.warn("异常信息:{}", e.getMessage());
        log.warn("异常跟踪信息如下:", e); // 输出异常信息时,第1个参数中不要使用占位符
        // e.printStackTrace();
        return message;
    }
}

四、使用全局异常类

import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.web.ServiceCode;
import org.springframework.web.bind.annotation.*;

@ResponseBody
@RestController
public class test {
    /**
     * 除法计算
     */
    @GetMapping("/divide/{a}/{b}")
    public int divide(@PathVariable("a") int a, @PathVariable("b") int b){
        if(b==0){
            throw new ServiceException(ServiceCode. BAD_REQUEST ,"被除数b为0");
            //throw new ServiceException(400,"b为0");
        }
       return a/b;
    }
    /**
     * 模拟添加字符串到数组
     */
    @GetMapping("/addToArr/{a}")
    public String addToArr(@PathVariable("a") String txt){
        String [] a = {};
        a[1]=txt;
        return  "模拟字符串添加进数组";
    }

}

测试的内容

除法测试

 

springboot中全局异常拦截器MyExceptionHandler咋没用 springboot全局异常处理原理_spring

springboot中全局异常拦截器MyExceptionHandler咋没用 springboot全局异常处理原理_spring_02

 

模拟添加字符串到数组测试


springboot中全局异常拦截器MyExceptionHandler咋没用 springboot全局异常处理原理_json_03

 综上所述:全局异常处理可以将运行时的异常进行封装,当出现异常时返回异常编码和异常信息的JSON信息,且面对不同的异常通过设置不同的message来设置响应的异常信息。

可以用于减少代码量,使前端可以快速的判断不同的响应状态

且可以对全局异常进行输出(不会返回500响应)