Spring Boot @RestControllerAdvice 統(tǒng)一異常處理

在做前后端分離的項目時,后端通常都會拆分成多個獨立的微服務(wù),這時候就會涉及每個服務(wù)返回給前端的數(shù)據(jù)格式問題了。下面就來實現(xiàn)一個比較常用的數(shù)據(jù)格式,統(tǒng)一所有服務(wù)的返回值格式。
一般返回的數(shù)據(jù)格式會包括4個部分,第一部分: 請求處理是否成功,第二部分:服務(wù)處理結(jié)果編碼,第三部分:編碼對應(yīng)的文本信息,第四部分:返回值。如下所示:

{
    "result": true,
    "code": 1000,
    "message": "SUCCESS",
    "data": {
        "lantian": 17,
        "qingfen": 16,
        "baiyun": 18
    }
}

對于異常處理情況,我們也需要統(tǒng)一成上面的格式。如果我們在controller中通過try catch來處理異常的話,會出現(xiàn)一個問題就是每個函數(shù)里都加一個Try catch,代碼會變的很亂。下面我們就通過spring boot的注解來省略掉controller中的try-catch 幫助我們來封裝異常信息并返回給前端,這樣用戶也不會得到一些奇奇怪怪的錯誤提示。

{
    "result": false,
    "code": 3000,
    "message": "THIS IS AN UNKNOW EXCEPTION",
    "data": null
}

1:定義返回值結(jié)構(gòu)信息(get, set函數(shù)省略)

public class CallResultMsg<T> {
    private boolean result;
    private int code;
    private String message;
    private T data;
}

2:定義返回值和對應(yīng)code的信息(get, set函數(shù)省略)

public enum CodeAndMsg {
    SUCCESS(1000, "SUCCESS"),
    METHODFAIL(2000, "ENCOUNTER AN ERROR WHEN EXECUTE METHOD"),
    UNKNOWEXCEPTION(3000, "THIS IS AN UNKNOW EXCEPTION");

    private int code;
    private String msg;

    CodeAndMsg(int code, String msg){
        this.code = code;
        this.msg = msg;
    }
}

3:自定義異常

對于一些特別的異常,我們可以自定義Exception和Error Code,這里自定義一個異常(需要繼承RuntimeException)

public class UserDefinedException extends RuntimeException {
    private CodeAndMsg exception;

    public UserDefinedException(CodeAndMsg exception){
        this.exception = exception;
    }

    public CodeAndMsg getException() {
        return exception;
    }

    public void setException(CodeAndMsg exception) {
        this.exception = exception;
    }
}

4:RestControllerAdvice來捕獲全局異常,

@RestControllerAdvice都是對Controller進(jìn)行增強(qiáng)的,可以全局捕獲spring mvc拋的異常。
@ExceptionHandler(value = Exception.class)
ExceptionHandler的作用是用來捕獲指定的異常。

@RestControllerAdvice(annotations = RestController.class)
public class UniformReponseHandler<T> {

    @ResponseStatus(HttpStatus.OK)
    public CallResultMsg sendSuccessResponse(){
        return new CallResultMsg(true, CodeAndMsg.SUCCESS, null);
    }

    @ResponseStatus(HttpStatus.OK)
    public CallResultMsg sendSuccessResponse(T data) {
        return new CallResultMsg(true, CodeAndMsg.SUCCESS, data);
    }

    @ExceptionHandler(UserDefinedException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public CallResultMsg sendErrorResponse_UserDefined(Exception exception){
        return new CallResultMsg(false, ((UserDefinedException)exception).getException(), null);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public CallResultMsg sendErrorResponse_System(Exception exception){
        if (exception instanceof UserDefinedException) {
            return this.sendErrorResponse_UserDefined(exception);
        }

        return new CallResultMsg(false, CodeAndMsg.UNKNOWEXCEPTION, null);
    }
}

通過上面的一波操作,我們的controller中就不需要再去寫大量的try-catch了,RestControllerAdvice會自動幫助catch,并匹配相應(yīng)的ExceptionHandler,然后重新封裝異常信息,返回值,統(tǒng)一格式返回給前端。
\color{ red }{ 當(dāng)然也可以單獨寫成一個jar包,供其他微服務(wù)的使用。 }

5:ControllerAdvice 和 RestControllerAdvice的區(qū)別

@ControllerAdvice 和 @RestControllerAdvice都是對Controller進(jìn)行增強(qiáng)的,可以全局捕獲spring mvc拋的異常。
RestControllerAdvice = ControllerAdvice + ResponseBody
6:測試統(tǒng)一異常捕獲功能

@GetMapping("/doTestObject")
public CallResultMsg testObjectReturn(){
    Map<String, Integer> map = new HashMap();
    map.put("qingfen", 16);
    map.put("lantian", 17);
    map.put("baiyun", 18);
    return new UniformReponseHandler<Map>().sendSuccessResponse(map);
}


@GetMapping("/doTestException/{x}")
public int testExceptionResturn(@PathVariable int x){
    if (0 < x && x < 10){
        throw new UserDefinedException(CodeAndMsg.METHODFAIL);
    } else {
        return  1/0;
    }
}

返回結(jié)果:

{
    "result": true,
    "code": 1000,
    "message": "SUCCESS",
    "data": {
        "lantian": 17,
        "qingfen": 16,
        "baiyun": 18
    }
}
{
    "result": false,
    "code": 2000,
    "message": "ENCOUNTER AN ERROR WHEN EXECUTE METHOD ",
    "data": null
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容