SpringBoot统一异常处理解决思路
对于一个完美的项目,异常处理是必不可少的。SpringBoot的统一异常处理,可以让项目出现的绝大多数异常都在你的把控之类。废话不多说,直接上干货。
首先先知道一下SpringBoot统一异常处理四剑客(四模板),1. 异常类型枚举类,2.自定义异常,3.统一信息返回类,4.全局异常处理类。现在不懂没关系,后面会讲。

第一个干货 @ControllerAdvice注解
@ControllerAdvice注解有三个用途,全局异常处理,全局数据绑定,全局数据预处理。因为本篇文章是讲统一异常处理的,所以我们这里只讲其全局异常处理的用法。
那么@ControllerAdvice有什么用呢?所以Controller抛出来的异常都能由被@ControllerAdvice注解的类来进行异常处理。当然还要结合@ExceptionHandler注解。上代码!
这里我们先不要关注R是什么,后面会将。@ControllerAdvice类注解注解标明这个类被用来处理Controller抛出来的所有异常。@ExceptionHandler方法加异常类的字节码对象参数标明该方法用来处理的异常类型。比如RRExceptionHandle方法用来处理RRException(自定义异常,后面会讲)这个异常及其子类,而如果Contrller抛出NullPointException异常则不会由RRExceptionHandle这个方法来处理。
/**
* controller 统一异常处理
*/
@ControllerAdvice
public class CommonExceptionHandle {
@ResponseBody
@ExceptionHandler(RRException.class)
public R RRExceptionHandle(RRException exception){
return R.error(exception.getCode(),exception.getMsg());
}
@ResponseBody
@ExceptionHandler(RuntimeException.class)
public R RuntimeExceptionHandle(RuntimeException runtimeException){
return R.error(500,runtimeException.getMessage());
}
}
异常类型枚举类
异常枚举类,通过设置枚举类型和自定义异常结合起来,可以很方便的定义各种类型的异常。(@Getterd得装lombok插件才能使用)
@Getter
public enum ExceptionEnum {
ADMINISTRATOR_UPDATE_FAILED(5000,"管理员更新错误"),
ADMINISTRATOR_SAVE_FAILED(5001,"管理员保存错误"),
ADMINISTRATOR_DELETE_FAILED(5002,"管理员删除错误")
;
private final int code;
private final String msg;
ExceptionEnum(int code,String msg){
this.code = code;
this.msg = msg;
}
}
使用场景
@PutMapping(value = "")
public R update(@RequestBody AdministratorEntity administrator){
logger.info("administrator update函数入参为:{}",administrator);
boolean update = administratorService.updateById(administrator);
if(!update){
throw new RRException(ExceptionEnum.ADMINISTRATOR_UPDATE_FAILED);
}
logger.info("administrator update函数是是否成功为:{}",update);
return R.ok().put("data","");
}
自定义异常
自定义异常集成运行时异常类,提供一个异常枚举类的构造方法即可。
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(ExceptionEnum exceptionEnum) {
super(exceptionEnum.getMsg());
this.msg = exceptionEnum.getMsg();
this.code = exceptionEnum.getCode();
}
public String getMsg() {
return msg;
}
public int getCode() {
return code;
}
}
统一数据格式返回类
该类用来统一后台返回数据给前端的格式。
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}
全局异常处理类
这边一个ExceptionHandle处理自定义异常,但是除了自定义异常可能还会有未知的异常,未知的异常也都是运行时异常,所以我们在添加一个方法用来处理未知异常。
@ControllerAdvice
public class CommonExceptionHandle {
/**
* 处理自定义异常
*/
@ResponseBody
@ExceptionHandler(RRException.class)
public R RRExceptionHandle(RRException exception){
return R.error(exception.getCode(),exception.getMsg());
}
/**
* 处理未知错误
*/
@ResponseBody
@ExceptionHandler(RuntimeException.class)
public R RuntimeExceptionHandle(RuntimeException runtimeException){
return R.error(500,runtimeException.getMessage());
}
}