一. 走進自定義統一異常
1.1 什麼是自定義統一異常
- 我們在寫代碼的時候,對異常處理一般是try catch或者拋出異常throws Exception。
- try catch大家都知道,代碼中大量的try catch會佔用內存影響性能,而且需要在每個方法的代碼塊加上try catch,非常的繁瑣;throws Exception也一樣需要加在每個方法後面;
- 自定義異常就是,當我們認爲可能爲出現錯誤的地方,不進行try…catch,而是向上層拋出,由最頂層的異常處理類進行統一處理。在這裏,我們可以對異常進行針對性的處理,比如加日誌,不同異常返回不同結果等。
- Java雖然提供了豐富的異常處理類,但是在項目中還會經常使用自定義異常,其主要原因是Java提供的異常類在某些情況下還是不能滿足實際需球。例如以下情況:
1、系統中有些錯誤是符合Java語法,但不符合業務邏輯。
2、在分層的軟件結構中,通常是在表現層統一對系統其他層次的異常進行捕獲處理。 總結來說,自定義統一異常,就是我們自己定義一個異常類,在可能出現異常的地方進行手動拋出,由統一異常類進行統一處理。
1.2 優缺點
- 優點:
- 代碼簡潔美觀,提升開發效率,易於理解
- 易於維護和發現問題,易於統一處理
- 缺點:
- 要自定義異常和統一異常,增加代碼量;
1.3 適用面
- 統一異常基本在所有的項目中均可使用。尤其適用於邏輯較爲複雜,業務較爲繁瑣,問題難以排查,代碼量比較多,項目比較大的地方。
- 建議是每個項目都可以做異常處理類,規範化的處理好過雜亂無序。
二. 使用自定義統一異常
2.1 示例圖片
- 拋出異常後,返回異常對象一:
- 拋出異常後,返回異常對象二:
- 未拋出異常後,返回成功對象:
2.2 實戰代碼
- 首先,定義一個異常類
package com.xxx.xxx.exception;
import com.xxx.xxx.base.util.common.ResultBean;
import lombok.Data;
/**
* @program: xxx
* @description:
* @author: anyu
* @create: 2020-05-09
*/
@Data
public class BusinessException extends RuntimeException{
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
- 定義一個異常處理類
package com.xxx.xxx.exception;
/**
* @program: xxx
* @description: 統一異常處理
* @author: anyu
* @create: 2020-05-09
*/
import com.jtd.adp5.base.util.SessionUtil;
import com.jtd.adp5.base.util.common.ResultBean;
import com.jtd.adp5.dao.po.SysAdmin;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @作者 weyoung
* @功能描述 給控制器請求添加默認常用參數,統一處理異常
* @日期 2019/3/4
*/
@ControllerAdvice
public class ControllerAdviceHandler {
private static final Logger logger = Logger.getLogger(ControllerAdviceHandler.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultBean exceptionHandler(Exception ex) {
// 處理業務異常
if (ex instanceof BusinessException) {
logger.error("異常類型爲:BusinessException,提示信息爲:"+ex.getMessage()+";下面爲詳細日誌", ex);
return ResultBean.createResultByError((ex.getMessage()));
} else {
logger.error("異常類型爲:Exception,提示信息爲:"+ex.getMessage()+";下面爲詳細日誌", ex);
return ResultBean.createResultByError(ex.getMessage());
}
}
}
- 統一返回Bean對象:
public class ResultBean {
private String msg;
private String code;
private Object result;
private Integer pageNumber;
private Integer pageSize;
// 省略,get、set、以及構造方法
}
- Controller層代碼:
@RestController
@RequestMapping("api")
@Slf4j
public class ArticlePublishController {
/**
* 查詢文章信息
*
* @param req
* @return
*/
@RequestMapping(value = "xxx", method = RequestMethod.POST)
public ResultBean articleList() throws Exception {
// throw new BusinessException("分頁參數小於0,請檢查後再試!");
// throw new BusinessException("請登錄後查詢!");
return ResultBean.createResultBySuccess("成功!");
}
當返回成功時,即返回 成功信息 。 如果拋出異常,則會根據異常不同進行分別處理。
2.3 注意事項
- 統一異常處理需要 @ControllerAdvice 註解。
- 在擴展異常時,我們可以創建多個異常類,對每個異常類進行分別的處理。同時,我們也可以分別給特定的錯誤碼,與實際業務結合起來。