前後端分離開發中,後端服務器有很多異常,而在業務層如果直接拋出異常信息對前端的信息展示非常不友好,所以此文介紹一種目前前後端分離開發中常用的統一異常處理方法。
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測試: