一、什么是异常处理

异常(Exception)是程序在运行时可能出现的会导致程序运行终止的错误。这种错误是不能通过编译系统检查出来的,如果不进行异常处理,程序将中断无法提供服务。

二、如何使用Spring Boot异常处理

项目结构:

springboot不抛出异常注解 springboot的异常处理机制_Java

案例

获取某个女生的年龄并判断小于10,返回应该还在上小学大于10且小于16,返回可能在上初中!

1.创建实体Girl类

@Entity
@Data
/**
 * fasterxml.jackson 将对象转换为json报错处理方法:
 *  在实体类Girl上添加@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })解决
 */
@JsonIgnoreProperties(value = { "hibernateLazyInitializer", "handler" })
public class Girl {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @NotBlank(message = "这个字段必传")
    private String cupSize;

    @NotNull(message = "金额必传")
    private Double money;

    @Min(value = 18, message = "年龄必须大于18岁")
    private Integer age;
}

2.创建ResponseVO类用于响应前端请求数据

@Data
/* 1.定义一个封装类,用于封装数据返回给前端*/
public class ResponseVO<T>  {
    /*错误码*/
    private Integer code;
    /*提示信息*/
    private String msg;
   /* 使用泛型封装数据*/
    private T data;
}

3.创建ResultEnum枚举用来管理异常信息

**
 *  使用枚举类关联错误码
 */
@Getter
public enum ResultEnum {
    UNKNOW_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;
    }
}

4.创建ResultUtil工具类

作用:封装数据响应前端请求

/*编写一个工具类*/
public class ResultUtil {

    /* 1.返回成功显示的数据*/
    public static ResponseVO success(Object object) {
        ResponseVO result = new ResponseVO();
        result.setCode(0);
        result.setMsg("成功");
        result.setData(object);
        return result;
    }

    public static ResponseVO success() {
        return success(null);
    }
    /* 1.返失败携带的数据*/
    public static ResponseVO error(Integer code, String msg) {
        ResponseVO result = new ResponseVO();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
}

5.创建GirlController接口接收前端请求

/**
     * 通过id查询一个对象的年龄,并判断大小,返回不同结果
     * @param id
     * @return
     * @throws Exception
     */
    @GetMapping(value = "/girls/getAge/{id}")
    public ResponseVO getGirlById(@PathVariable("id") Integer id) throws Exception{
        return ResultUtil.success(girlService.getAge(id));
    }

情况一:当id=1从数据库查询出年龄为6岁小于10,因此抛出异常!刚好被ExceptionHandle接收并处理。

结果为:

springboot不抛出异常注解 springboot的异常处理机制_Java_02

情况二: 当id=3从数据库查询出年龄为20岁大于16,因此无异常发生,正常返回数据给前端。

结果为:

springboot不抛出异常注解 springboot的异常处理机制_Java_03

6.创建GirlService类,处理业务有异常往外抛!

@Service
public class GirlService {

    @Autowired
    private GirlRepository girlRepository;

    public Girl getAge(Integer id)throws Exception{
        Girl girl=girlRepository.getOne(id);
        Integer age=girl.getAge();

        if (age<10){
            //返回“你可能在上小学” code=100
            throw new GirlException(ResultEnum.PRIMARY_SCHOOL);
        }else if(age>10 && age<16){
            //返回“你可能在上初中” code=101
            throw new GirlException(ResultEnum.MIDDLE_SCHOOL);
        }
        return girl;
    }
}

7.创建异常类GirlException封装异常信息

public class GirlException extends RuntimeException {
    private Integer code;

    public GirlException(ResultEnum resultEnum) {
        //父类的构造方法本身会传message进去
        super(resultEnum.getMsg());
        this.code = resultEnum.getCode();
    }

    public Integer getCode() {
        return code;
    }
}

8.创建统一异常处理ExceptionHandle类,用于处理service发生的异常!

如果service层业务出现异常,直接跳到统一异常处理类中处理异常!

/**
 * @ControllerAdvice + @ExceptionHandler 组合进行的 Controller 层上抛出
 * 异常全局统一处理
 */
@ControllerAdvice
public class ExceptionHandle {

    //记录系统异常
    private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);

    /**
     * 1.@ExceptionHandler(GirlException.class) 声明了对 GirlException业务异常的处理,
     * 并获取该业务异常中的错误提示,构造后返回给客户端。
     *
     * 2.@ExceptionHandler(Exception.class) 声明了对 Exception 异常的处理,起到兜底作用,
     * 不管 Controller 层执行的代码出现了什么未能考虑到的异常,都返回统一的错误提示给客户端。
     */

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseVO handle(Exception e) {
        /* 判断异常对象*/
        if (e instanceof GirlException) {
            GirlException girlException = (GirlException) e;
            return ResultUtil.error(girlException.getCode(), girlException.getMessage());
        } else {
            logger.error("【系统异常】 {}",e);
            return ResultUtil.error(-1, "未知错误");
        }
    }
}