为什么需要做统一异常处理:
因为如果不做统一处理,返回与前端的数据会非常乱,前端不好处理;并且不做统一处理,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规范的数据格式
*/
@ControllerAdvice
public 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规范的数据格式
*/
@ControllerAdvice
public 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()));
}