前后端分离开发中,后端服务器有很多异常,而在业务层如果直接抛出异常信息对前端的信息展示非常不友好,所以此文介绍一种目前前后端分离开发中常用的统一异常处理方法。
1. 自定义错误状态码接口(CustomizeErrorCode)
/**
* @author Jack
* @date 2019-07-27-18:08
*/
public interface CustomizeErrorCode {
/**
* 获取错误状态码
* @return 错误状态码
*/
Integer getCode();
/**
* 获取错误信息
* @return 错误信息
*/
String getMessage();
}
2. 枚举类型的错误状态码(MyCustomizeErrorCode)
这个类实现CustomizeErrorCode,必须实现它的方法
/**
* @author Jack
* @date 2019-07-27-18:07
*/
public enum MyCustomizeErrorCode implements CustomizeErrorCode {
/**
* 3005:"密码不正确!"
*/
PASS_NOT_CORRECT(3005, "密码不正确!请重新尝试!"),
/**
* 3006:"尚未登录!"
*/
NOT_LOGIN(3006, "尚未登录!"),
/**
* 2005:"没有找到这一条历史信息!有人侵入数据库强制删除了!"
*/
INTRODUCTION_NOT_FOUND(2005, "没有找到这一条历史信息!有人侵入数据库强制删除了!"),
/**
* 404:没有找到对应的请求路径
*/
PAGE_NOT_FOUND(404, "你要请求的页面好像暂时飘走了...要不试试请求其它页面?"),
/**
* 500:服务端异常
*/
INTERNAL_SERVER_ERROR(500, "服务器冒烟了...要不等它降降温后再来访问?"),
/**
* 2001:未知异常
*/
INTERNAL_SERVER_ERROR(2001, "未知异常,请联系管理员!"),
private String message;
private Integer code;
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
MyCustomizeErrorCode(Integer code, String message) {
this.message = message;
this.code = code;
}
}
3. 自定义异常类(CustomizeException)
这个类继承RuntimeException类,有两个属性code和message,抛出该异常时返回前端的JSON信息只包含这2个字段,构造方法需要传入枚举类型的错误状态码,意思就是说如果要抛出异常,需要指定抛出自定义的哪一个异常信息。
/**
* @author Jack
* @date 2019-07-27-18:36
*/
public class CustomizeException extends RuntimeException {
private Integer code;
private String message;
public CustomizeException(CustomizeErrorCode customizeErrorCode) {
this.code = customizeErrorCode.getCode();
this.message = customizeErrorCode.getMessage();
}
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
4. 统一异常处理类(CustomizeExceptionHandler)
/**
* @author Jack
* @date 2019-07-27-18:34
*/
@ControllerAdvice
public class MyCustomizeExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
@Override
public ResultDTO handleCustomizeException(HttpServletRequest request, Throwable ex) {
//获取错误状态码
HttpStatus status = getStatus(request);
//判断是否匹配自定义异常
if (ex instanceof CustomizeException) {
CustomizeException customizeException = (CustomizeException) ex;
ResultDTO resultDTO = ResultDTO.errorOf(customizeException.getCode(), customizeException.getMessage());
System.out.println(resultDTO.toString());
return resultDTO;
}
//判断是否5xx类型异常
if (status.is5xxServerError() || ex instanceof ParseException) {
ResultDTO resultDTO = ResultDTO.errorOf(MyCustomizeErrorCode.INTERNAL_SERVER_ERROR);
return resultDTO;
}
return ResultDTO.errorOf(MyCustomizeErrorCode.UNKNOWN_ERROR);
}
}
5. 统一封装Json类(JsonResultUtil)
/**
* @author Jack
* @date 2019-06-27-17:00
*/
@Data
public class JsonResultUtil implements Serializable {
private Integer code;
private String msg;
private Map<String, Object> extended = new HashMap<>();
public static JsonResultUtil success(){
return new JsonResultUtil(200, "处理成功");
}
public static JsonResultUtil fail(){return new JsonResultUtil(100, "处理失败!");}
public static JsonResultUtil errorOf(CustomizeErrorCode errorCode){
return errorOf(errorCode.getCode(), errorCode.getMessage());
}
public static JsonResultUtil errorOf(Integer code, String message) {
return new JsonResultUtil(code, message);
}
public JsonResultUtil addObject(String key, Object value){
this.extended.put(key, value);
return this;
}
public JsonResultUtil(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
示例:
/**
* @author Jack
* @date 2019-07-28-14:08
*/
@Service
public class AdminIntroductionServiceimpl implements AdminIntroductionService {
@Autowired
IntroductionDao introductionDao;
/**
* 更新介绍内容
*/
@Override
public void updateIntroduction(Long introductionId, String introductionInfo) {
Introduction dbIntroduction;
try {
dbIntroduction= introductionDao.findById(introductionId).get();
}catch (Exception ex){
//抛出自定义异常,该介绍内容不存在
throw new CustomizeException(MyCustomizeErrorCode.INTRODUCTION_NOT_FOUND);
}
Date currentTime = DateUtil.getCurrentDateTime();
dbHistory.setIntroductionEditTime(currentTime);
dbHistory.setIntroductionInfo(introductionInfo);
historyDao.save(dbHistory);
}
}
Postman测试: