SpringMVC Controllrt 層的異常處理 (@ExceptionHandler)


SpringMVC Controllrt 層的異常處理 :

 一、統一的返回格式

  當我向前端返回數據時,無論是否成功,我都希望能提供一個統一的返回格式,和一個友善的錯誤提示。所以在完成異常處理前,先提供一個統一的返回格式CommonReturnType,它暫時含有兩個字段

  status 表示上傳數據成功或者失敗,data  則是要 上傳的數據。當成功上傳數據時,status 為 “success ”,data 為 數據;當失敗時 status 為 “fail”, data 為 錯誤的詳細。

    private String status;

    private Object data;

  代碼:

package com.snapshot2.demo.response;

/**
 * 通用的返回體,用於向前端返回一個通用的數據結構體
 */
public class CommonReturnType {
    //表明返回的類型是"success " 或者 "fail"
    private String status;
    //若status = success data內放回前端需要的數據
    //若status = fail data內返回相應的錯誤信息
    private Object data;

    /* 兩種創建方法 */
    /**
     * 當只傳入數據data 時,默認成功
     * @param result
     * @return
     */
    public static CommonReturnType creat(Object result){
        return creat(result,"success");
    }

    /**
     * 當傳入status 和 object 時使用這個創建方法
     * @param result
     * @param status
     * @return
     */
    public static CommonReturnType creat(Object result, String status){
        CommonReturnType commonReturnType = new CommonReturnType();
        commonReturnType.setData(result);
        commonReturnType.setStatus(status);
        return commonReturnType;
    }

    /* 省略 Getter and Setter */

  二、使用裝飾器模式來自定義一個Controller 層的異常

    我們使用一個枚舉來定義自己的一些異常類型,然后使用裝飾器模式來實現對應的功能:

    UML 類設計圖:

    

    代碼實現:

   CommonErr:

 

package com.snapshot2.demo.error;

/**
 * 通用的異常接口,整合后端異常反饋給前端,使用裝飾器模式
 * 這是裝飾器的統一接口
 */
public interface CommonError {
    public int getErrCode();
    public String getErrMsg();
    public CommonError setErrMsg(String errMsg);
}

 

  CommonErrEnum:

package com.snapshot2.demo.error;

public enum CommonErrEnum implements CommonError {

    //00001 通用的參數不合法錯誤碼
    PARAMTER_VALIDATION_ERROR(00001,"參數不合法"),
    UNKOWN_ERROR(00002,"未知錯誤"),
    //10000開頭的錯誤碼代表用戶信息相關的錯誤
    USER_NOT_EXIST(100001,"用戶不存在");

    private int errCode;
    private String errMsg;
    /* Constructor */

    CommonErrEnum(int errCode, String errMsg) {
        this.errCode = errCode;
        this.errMsg = errMsg;
    }

    @Override
    public int getErrCode() {
        return this.errCode;
    }

    @Override
    public String getErrMsg() {
        return this.errMsg;
    }

    @Override
    public CommonError setErrMsg(String errMsg) {
        this.errMsg = errMsg;
        return this;
    }
}

  UserExceprion

package com.snapshot2.demo.error;

/**
 * 使用到了包裝器模式
 */
public class UserException extends Exception implements CommonError {

    //強關聯一個CommonError(CommonErrorEnum)
    private CommonError commonError;

    //直接接受一個CommonEnum,用於構造一個業務異常
    public UserException(CommonError commonError){
        //調用Exception的初始化機制
        super();
        this.commonError = commonError;
    }

    /* Constructor */
    public UserException(CommonError commonError,String errMsg){
        super();
        this.commonError = commonError;
        this.commonError.setErrMsg(errMsg);
    }

    public void setCommonError(CommonError commonError) {
        this.commonError = commonError;
    }


    @Override
    public int getErrCode() {
        return this.commonError.getErrCode();
    }

    @Override
    public String getErrMsg() {
        return this.commonError.getErrMsg();
    }

    @Override
    public CommonError setErrMsg(String errMsg) {
        this.commonError.setErrMsg(errMsg);
        return this.commonError;
    }
}

  我們可以看到,UserException 繼承與Exception類,又實現了CommonErr接口。它關聯了一個實現CommonErr接口的類(這里就是我們定義的Enum類),並且可以使用並增強它的方法。

  之后我們就可以在Controller層使用@ExceptionHandler(Exception.class) 注解來捕獲在Controler層出現的Exception異常,並且消化它,向前端返回友善的錯誤提示:

    //定義ExceptionHandler解決Controller層未被處理掉的異常
    @ExceptionHandler(Exception.class)
    //Controller 層返回的異常應該屬於后端的異常
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Object handlerException(HttpServletRequest request, Exception e){
        Map<String,Object> responseData = new HashMap<>();
        CommonReturnType commonReturnType = new CommonReturnType();
        if(e instanceof UserException){
            //強制轉化捕獲的錯誤為UserException
            UserException userException = (UserException)e;
            //將錯誤信息轉化為通用的上傳格式
            commonReturnType.setStatus("fail");
            //將自定義的Exception 信息提取出來放在返回體中
            responseData.put("errCode",userException.getErrCode());
            responseData.put("errMsg",userException.getErrMsg());
            commonReturnType.setData(responseData);
        } else{
            responseData.put("errCode",CommonErrEnum.UNKOWN_ERROR.getErrCode());
            responseData.put("errMsg",CommonErrEnum.UNKOWN_ERROR.getErrMsg());
            commonReturnType.setStatus("fail");
            commonReturnType.setData(responseData);
        }
        return commonReturnType;

    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM