spring-boot-route(四)全域性異常處理

Java旅途發表於2020-10-04

在開發中,我們經常會使用try/catch塊來捕獲異常進行處理,如果有些程式碼中忘記捕獲異常或者不可見的一些異常出現,就會響應給前端一些不友好的提示,這時候我們可以使用全域性異常處理。這樣就不用在程式碼中寫那些煩人的try/catch塊了,程式碼的可讀性也會提高。

SpringBoot提供的的註解@ControllerAdvice表示開啟全域性異常捕獲,在自定義的異常方法上使用ExceptionHandler來進行統一處理。

下面一起看看如何優雅的處理全域性異常!

一 定義響應狀態碼及資訊的列舉類

@Getter
public enum CodeEnum {
    
    SUCCESS(0,"請求成功"),
    ERROR(500,"未知異常"),
    ERROR_EMPTY_RESULT(1001,"查詢結果為空"),
    ERROR_INCOMPLETE_RESULT(1002,"請求引數不全");
    
    private int code;
    private String message;
    CodeEnum(int code,String message){
        this.code = code;
        this.message = message;
    }
}

二 定義響應資料的實體類

@Slf4j
@Data
public class R<T> implements Serializable {

    private static final long serialVersionUID = 572235155491705152L;
    /**
     * 響應的狀態碼
     */
    private int code;
    /***
     * 響應的資訊
     */
    private String message;
    /**
     * 響應資料
     */
    private T data;

    /**
     * 放入響應碼並返回
     * @param code
     * @param msg
     * @return
     */
    public R fillCode(int code,String msg){
        this.code = code;
        this.message = msg;
        return this;
    }

    /**
     * 放入響應碼並返回
     * @param codeEnum
     * @return
     */
    public R fillCode(CodeEnum codeEnum){
        this.code = codeEnum.getCode();
        this.message = codeEnum.getMessage();
        return this;
    }

    /**
     * 放入資料並響應成功狀態
     * @param data
     * @return
     */
    public R fillData(T data){
        this.code = CodeEnum.SUCCESS.getCode();
        this.message = CodeEnum.SUCCESS.getMessage();
        this.data = data;
        return this;
    }
}

三 自定義兩個異常

根據業務需求自定義異常,在本文中我定義了兩個異常,分別用作響應結果為空時處理和請求引數錯誤時處理。

@Data
public class EmptyResutlException extends RuntimeException {

    private static final long serialVersionUID = -8839210969758687047L;
    private int code;
    private String message;

    public EmptyResutlException(CodeEnum codeEnum){
        this.code = codeEnum.getCode();
        this.message = codeEnum.getMessage();
    }
}
@Data
public class RequestParamException extends RuntimeException {

    private static final long serialVersionUID = 4748844811214637041L;
    private int code;
    private String message;

    public RequestParamException(CodeEnum codeEnum){
        this.code = codeEnum.getCode();
        this.message = codeEnum.getMessage();
    }
}

四 定義全域性異常處理類

由於這裡我想要響應的結果為實體類物件,因此我直接用@RestControllerAdvice來代替了@ControllerAdvice,這兩個註解的差別跟@Controller@RestController一樣,rest的響應體為json格式的資料。

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 查詢結果為空時處理
     * @param e
     * @return
     */
    @ExceptionHandler(EmptyResutlException.class)
    public R emptyResultExceptionHandler(EmptyResutlException e){
        log.error("查詢結果為空:{}",e.getMessage());
        R result = new R();
        result.fillCode(e.getCode(),e.getMessage());
        return result;
    }

    /**
     * 請求引數錯誤時處理
     * @param e
     * @return
     */
    @ExceptionHandler(RequestParamException.class)
    public R requestParamExceptionHandler(RequestParamException e){
        log.error("請求引數不合法:{}",e.getMessage());
        R result = new R();
        result.fillCode(e.getCode(),e.getMessage());
        return result;
    }

    /**
     * 處理其他異常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R exceptionHandler(Exception e){
        log.error("未知異常:{}",e.getMessage());
        R result = new R();
        result.fillCode(CodeEnum.ERROR);
        return result;
    }
}

五 自定義介面測試異常

@RestController
public class TestController {

    @GetMapping("getString")
    public R getString(String name){

        if(StringUtils.isEmpty(name)){
            throw new RequestParamException(1002,"請求引數name為空");
        }else if ("Java旅途".equals(name)) {
            // 這裡沒有查詢操作,當請求引數是Java旅途的時候,模擬成查詢結果為空
            throw new EmptyResutlException(1001,"查詢結果為空");
        }
        // 這裡模擬一下除自定義異常外的其他兩種異常
        int i = 0;
        i = 5/i;
        return new R().fillData(name);
    }
}

在實際開發中可以自定義響應狀態碼的列舉類和自定義異常以滿足需求。

此是spring-boot-route系列的第四篇文章,這個系列的文章都比較簡單,主要目的就是為了幫助初次接觸Spring Boot 的同學有一個系統的認識。本文已收錄至我的github,歡迎各位小夥伴star

githubhttps://github.com/binzh303/spring-boot-route

點關注、不迷路

如果覺得文章不錯,歡迎關注點贊收藏,你們的支援是我創作的動力,感謝大家。

如果文章寫的有問題,請不要吝嗇,歡迎留言指出,我會及時核查修改。

如果你還想更加深入的瞭解我,可以微信搜尋「Java旅途」進行關注。回覆「1024」即可獲得學習視訊及精美電子書。每天7:30準時推送技術文章,讓你的上班路不在孤獨,而且每月還有送書活動,助你提升硬實力!

相關文章