为什么需要做统一异常处理:
因为如果不做统一处理,返回与前端的数据会非常乱,前端不好处理;并且不做统一处理,controller层就要写很多的重复代码。
统一格式:
{
"code":10001,
"msg":"异常信息",
"data":null
}
{
"code":10000,
"msg":"SUCCESS",
"data":{
"id":20,
"name":"test",
"age":18
}
}
实现步骤:
- 新建Result对象——也就是请求返回的整体对象,包括code,msg,data
public class Result<T> { private Integer code ; private String msg; private T data; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
2.增加ResultUtil方法,封装设置Result数据的操作
/** * @author Qi.Zhang * 类说明:为避免controller层重复的set操作,遂添加ResultUtil */public class ResultUtil { //成功,有返回值 public static Result success(Object object){ Result result = new Result(); result.setCode(10000); result.setMsg("SUCCESS"); result.setData(object); return result; } //成功,没有返回值 public static Result success(){ return success(null); } //失败 public static Result error(Integer code , String errorMsg){ Result result = new Result(); result.setCode(code); result.setMsg(errorMsg); return result; } }
3.统一异常处理
/** * * @author Qi.Zhang * 类说明:统一异常处理 * Service抛异常到Controller,Controller继续抛异常 * 最终异常被这里捕获 * 我们让异常信息变成符合Result规范的数据格式 */@ControllerAdvicepublic class ExceptionHandle { @ExceptionHandler(value = Exception.class)//定义捕获异常的类型 @ResponseBody// 因为不是RestController,所以需要加这个,让它返回json格式 public Result handler(Exception e){ return ResultUtil.error(10001, e.getMessage()); }}4.使用枚举统一管理异常信息(是必要的)
/** * @author Qi.Zhang * 类说明:使用枚举统一维护信息 */public enum ResultEnum { SUCCESS(10000,"SUCCESS"), UNKNOWN_ERROR(10002,"未知错误") ; private Integer code; private String msg; private ResultEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; }}
5.区分系统异常以及自定义异常捕获
注意:自定义异常需要 extends RuntimeException;
原因:spring只对RuntimeException才进行事物回滚,Exception不管的
- 自定义异常
/** * @author Qi.Zhang * 类说明:自定义异常 */public class MyException extends RuntimeException { private Integer code; //自定义异常code 异常消息 public MyException(Integer code,String message) { super(message); this.code = code; } //从枚举中获取定义好的信息 public MyException(ResultEnum e) { super(e.getMsg()); this.code = e.getCode(); } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
- 改造第3步,完善统一异常处理
/** * * @author Qi.Zhang * 类说明:统一异常处理 * Service抛异常到Controller,Controller继续抛异常 * 最终异常被这里捕获 * 我们让异常信息变成符合Result规范的数据格式 */@ControllerAdvicepublic class ExceptionHandler { //在日志中记录异常 private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class); @ExceptionHandler(value = Exception.class) @ResponseBody public Result handler(Exception e){ if (e instanceof MyException) { MyException myException = (MyException)e; return ResultUtil.error(myException.getCode(), myException.getMessage()); } logger.error("系统异常{}",e); return ResultUtil.error(10001, e.getMessage()); }}使用
@GetMapping(value="/healthLevelData")public String getHealthLevelData(){ return new Gson().toJson(ResultUtil.success(dimCacheImpl.getDimHealthLevelList()));}