一、什么是异常处理
异常(Exception)是程序在运行时可能出现的会导致程序运行终止的错误。这种错误是不能通过编译系统检查出来的,如果不进行异常处理,程序将中断无法提供服务。
二、如何使用Spring Boot异常处理
项目结构:
案例:
获取某个女生的年龄并判断小于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接收并处理。
结果为:
情况二: 当id=3从数据库查询出年龄为20岁大于16,因此无异常发生,正常返回数据给前端。
结果为:
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, "未知错误");
}
}
}