SpringBoot使用萬能的統一異常處理方法返回異常信息

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

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測試:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章