欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot優(yōu)雅地實(shí)現(xiàn)全局異常處理的方法詳解

 更新時(shí)間:2022年08月18日 14:11:29   作者:慕歌  
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何優(yōu)雅地實(shí)現(xiàn)全局異常處理,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

在前一節(jié)的學(xué)習(xí)中,慕歌帶大家使用了全局結(jié)果集返回,通過使用全局結(jié)果集配置,優(yōu)雅的返回后端數(shù)據(jù),為前端的數(shù)據(jù)拿取提供了非常好的參考。同時(shí)通過不同的狀態(tài)碼返回,我們能夠清晰的了解報(bào)錯(cuò)的位置,排除錯(cuò)誤。如果大家有需要,可以使用我提供的的同一結(jié)果集以及狀態(tài)碼,并且可以使用全局異常攔截,實(shí)現(xiàn)異常的標(biāo)準(zhǔn)返回。接下來,我們一起來了解如何使用全局異常處理吧!

異常工具

先定義一個(gè)合適 的異常處理類,在之后的異常都會以這種格式返回前端,前端根據(jù)我們的異常進(jìn)行自己的返回,以一種優(yōu)雅的方式呈現(xiàn)錯(cuò)誤,優(yōu)化用戶體驗(yàn)。
異常結(jié)果集:

/**
 * 返回結(jié)果封裝
 */

@Data
public class ResultVo {
    // 狀態(tài)碼
    private int code;

    // 狀態(tài)信息
    private String msg;

    // 返回對象
    private Object data;

    // 手動(dòng)設(shè)置返回vo
    public ResultVo(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    // 手動(dòng)設(shè)置返回vo
    public ResultVo(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    // 只返回狀態(tài)碼
    public ResultVo(StatusCode statusCode) {
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
    }

    // 默認(rèn)返回成功狀態(tài)碼,數(shù)據(jù)對象
    public ResultVo(Object data) {
        this.code = ResultCode.SUCCESS.getCode();
        this.msg = ResultCode.SUCCESS.getMsg();
        this.data = data;
    }

    // 返回指定狀態(tài)碼,數(shù)據(jù)對象
    public ResultVo(StatusCode statusCode, Object data) {
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
        this.data = data;
    }

    public ResultVo(StatusCode statusCode,String msg, Object data) {
        this.code = statusCode.getCode();
        this.msg = msg;
        this.data = data;
    }
}

異常狀態(tài)碼,通過返回的狀態(tài)碼,以及狀態(tài)信息,能夠高效反映錯(cuò)誤,并且可以全局統(tǒng)一管理,方便快捷:

@Getter
public enum ExceptionCode implements StatusCode {

    // 系統(tǒng)級別錯(cuò)誤碼
    ERROR(-1, "操作異常"),
    NOT_LOGIN(102, "請先登錄!"),
    NO_Role(102,"無權(quán)限"),
    NO_PERMISSION(102,"無權(quán)限"),
    OUT_TIME(102,"登錄信息過期"),
    DISABLE_ACCOUNT(102,"帳號已被禁用!"),
    EMAIL_DISABLE_LOGIN(102,"該郵箱賬號已被管理員禁止登錄!"),
    IP_REPEAT_SUBMIT(102,"訪問次數(shù)過多,請稍后重試"),
    ERROR_DEFAULT(105,"系統(tǒng)繁忙,請稍后重試");

    //異常碼
    private int code;
    //異常信息
    private String msg;

    //自定義方法
    ExceptionCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

當(dāng)我們對異常通過以上工具類進(jìn)行封裝之后,所有異常將以一種固定的格式返回,不會導(dǎo)致錯(cuò)亂:

{3 items
	"code":105
	"msg":"系統(tǒng)繁忙,請稍后重試"
	"data":NULL
}

異常處理

在spring boot中需要使用異常攔截器,攔截全局的異常,不直接將異常返回,而是在我們進(jìn)行處理之后,以一種清晰可讀的方式返回。并且前端能夠清晰解讀我們的異常,呈現(xiàn)給用戶。

//捕獲校驗(yàn)器異常
@RestControllerAdvice
public class ControllerExceptionAdvice {
    @ExceptionHandler({BindException.class})
    public ResultVo ValidExceptionHandler(BindException e) {
        // 從異常對象中拿到ObjectError對象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);

        return new ResultVo(ResultCode.VALIDATE_ERROR.getCode(),objectError.getDefaultMessage());
    }
}

對特定異常進(jìn)行攔截,并包裝異常:

/**
 * 對返回結(jié)果進(jìn)行包裝
 */
@RestControllerAdvice(basePackages = {"channel.cert"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // response是ResultVo類型,或者注釋了NotControllerResponseAdvice都不進(jìn)行包裝
        return !methodParameter.getParameterType().isAssignableFrom(ResultVo.class);
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        // String類型不能直接包裝
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 將數(shù)據(jù)包裝在ResultVo里后轉(zhuǎn)換為json串進(jìn)行返回
                return objectMapper.writeValueAsString(new ResultVo(data));
            } catch (JsonProcessingException e) {
                throw new APIException(ResultCode.RESPONSE_PACK_ERROR, e.getMessage());
            }
        }
        // 否則直接包裝成ResultVo返回
        return new ResultVo(data);
    }
}

異常捕捉

自定義異常:

@Getter
public class APIException extends RuntimeException {
    private int code;
    private String msg;

    //自定義異枚舉
    public APIException(StatusCode statusCode){
        super(statusCode.getMsg());
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
    }

    // 手動(dòng)設(shè)置異常
    public APIException(StatusCode statusCode, String message) {
        // message用于用戶設(shè)置拋出錯(cuò)誤詳情,例如:當(dāng)前價(jià)格-5,小于0
        super(message);
        // 狀態(tài)碼
        this.code = statusCode.getCode();
        // 狀態(tài)碼配套的msg
        this.msg = statusCode.getMsg();
    }

    // 默認(rèn)異常使用APP_ERROR狀態(tài)碼
    public APIException(String errorMsg) {
        super(errorMsg);
        this.code = ExceptionCode.ERROR_DEFAULT.getCode();
        this.msg = ExceptionCode.ERROR_DEFAULT.getMsg();
    }

    //自定義參數(shù) 錯(cuò)誤碼 錯(cuò)誤信息
    public APIException(int errorCode, String errorMsg) {
        super(errorMsg);
        this.code = errorCode;
        this.msg = ExceptionCode.ERROR_DEFAULT.getMsg();
    }

    //自定義參數(shù) 錯(cuò)誤碼 錯(cuò)誤信息 異常
    public APIException(int errorCode, String errorMsg, Throwable cause) {
        super(errorMsg);
        this.code = errorCode;
        this.msg = errorMsg;
    }
}

對自定義異常進(jìn)行捕獲,通過定義好的異常的結(jié)果集返回。

/**
 * 全局異常處理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {

    // Assert業(yè)務(wù)異常
    @ExceptionHandler(IllegalArgumentException.class)
    public ResultVo AssertExceptionHandler(IllegalArgumentException ex) {
        log.error( " msg : " + ex.getMessage(), ex);
        if(StringUtils.isBlank(ex.getLocalizedMessage())){
            return new ResultVo(ExceptionCode.ERROR_DEFAULT);
        }
        return new ResultVo(ex.getMessage());
    }

    // 登錄失效異常
    @ExceptionHandler(SaTokenException.class)
    public ResultVo LoginOutExceptionHandler(SaTokenException ex) {
        log.error( " msg : " + ex.getMessage(), ex);
        return new ResultVo(ExceptionCode.OUT_TIME);
    }

    // 登錄異常
    @ExceptionHandler(NotLoginException.class)
    public ResultVo NotLoginExceptionHandler(NotLoginException ex) {
        log.error( " msg : " + ex.getMessage(), ex);
        return new ResultVo(ExceptionCode.NOT_LOGIN);
    }

    // 權(quán)限異常
    @ExceptionHandler(NotPermissionException.class)
    public ResultVo NotPermissionExceptionHandler(NotPermissionException ex) {
        log.error( " msg : " + ex.getMessage(), ex);
        return new ResultVo(ExceptionCode.NO_PERMISSION);
    }

    //角色異常
    @ExceptionHandler(NotRoleException.class)
    public ResultVo NotRoleExceptionHandler(NotRoleException ex) {
        log.error( " msg : " + ex.getMessage(), ex);
        return new ResultVo(ExceptionCode.NO_Role);
    }

    //處理自定義異常
    @ExceptionHandler(APIException.class)
    public ResultVo APIExceptionHandler(APIException e) {
        log.error(e.getMessage(), e);
        return new ResultVo(e.getCode(), e.getMsg());
    }

    //處理運(yùn)行異常
    @ExceptionHandler(RuntimeException.class)
    public ResultVo RuntimeExceptionHandler(RuntimeException e) {
        log.error(e.getMessage(), e);
        return new ResultVo(ExceptionCode.ERROR_DEFAULT);
    }
}

通過以上自定義,我們就能在項(xiàng)目中,使用自定義異常,在我們認(rèn)為可能的報(bào)錯(cuò)處插入,當(dāng)發(fā)生錯(cuò)誤時(shí),我們更快定位是之前記錄的錯(cuò)誤點(diǎn)導(dǎo)致。

//查詢數(shù)字證書
    @Override
    public GroupUser searchCert(String certCode) {
        try {
            //查詢證書編號
            GroupUser user = queryCert(certCode);
            if(ObjectUtil.isNotNull(user)){
                return user;
            }
        }catch (Exception e){
            throw new APIException("區(qū)塊鏈調(diào)用失敗"+e);
        }
        return null;
    }

以上就是SpringBoot優(yōu)雅地實(shí)現(xiàn)異常處理的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot全局異常處理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot導(dǎo)入導(dǎo)出數(shù)據(jù)實(shí)現(xiàn)方法詳解

    SpringBoot導(dǎo)入導(dǎo)出數(shù)據(jù)實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了SpringBoot導(dǎo)入導(dǎo)出數(shù)據(jù)實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • 通過spring注解開發(fā),簡單測試單例和多例區(qū)別

    通過spring注解開發(fā),簡單測試單例和多例區(qū)別

    這篇文章主要介紹了通過spring注解開發(fā),簡單測試單例和多例區(qū)別,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java設(shè)計(jì)模式之原型模式詳解

    Java設(shè)計(jì)模式之原型模式詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳解,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • MyBatis-Plus雪花算法實(shí)現(xiàn)源碼解讀

    MyBatis-Plus雪花算法實(shí)現(xiàn)源碼解讀

    雪花算法是一種用于生成唯一標(biāo)識符(ID)的分布式算法,雪花算法的設(shè)計(jì)目標(biāo)是在分布式系統(tǒng)中生成全局唯一的ID,同時(shí)保證ID的有序性和趨勢遞增,這篇文章主要介紹了MyBatis-Plus雪花算法實(shí)現(xiàn)源碼解析,需要的朋友可以參考下
    2023-12-12
  • java實(shí)現(xiàn)簡單的圖書管理系統(tǒng)

    java實(shí)現(xiàn)簡單的圖書管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java利用Dijkstra算法求解拓?fù)潢P(guān)系最短路徑

    Java利用Dijkstra算法求解拓?fù)潢P(guān)系最短路徑

    迪杰斯特拉算法(Dijkstra)是由荷蘭計(jì)算機(jī)科學(xué)迪家迪杰斯特拉于1959年提出的,因此又叫狄克斯特拉算法。本文將利用迪克斯特拉(Dijkstra)算法求拓?fù)潢P(guān)系最短路徑,感興趣的可以了解一下
    2022-07-07
  • 一步步教你JAVA如何優(yōu)化Elastic?Search

    一步步教你JAVA如何優(yōu)化Elastic?Search

    想要榨干Java操作Elasticsearch的所有性能潛力?本指南將一步步教你如何優(yōu)化Java與Elasticsearch的交互!從此,提升ES查詢速度、降低資源消耗不再是難題,趕快一起來探索Java?Elasticsearch優(yōu)化的秘訣吧!
    2024-01-01
  • Java8深入學(xué)習(xí)系列(二)函數(shù)式編程

    Java8深入學(xué)習(xí)系列(二)函數(shù)式編程

    函數(shù)式編程,這個(gè)詞語由兩個(gè)名詞構(gòu)成,函數(shù),編程。編程這個(gè)詞我就不用解釋了,大家都是做這個(gè)的。函數(shù),其實(shí)單獨(dú)抽離出來這個(gè)詞語,也并不陌生,那二者組合后的到底是什么呢,下面這篇文章主要給大家介紹了關(guān)于Java8函數(shù)式編程的相關(guān)資料,需要的朋友可以參考下。
    2017-08-08
  • SpringMVC之RequestContextHolder詳細(xì)解析

    SpringMVC之RequestContextHolder詳細(xì)解析

    這篇文章主要介紹了SpringMVC之RequestContextHolder詳細(xì)解析,正常來說在service層是沒有request的,然而直接從controlller傳過來的話解決方法太粗暴,后來發(fā)現(xiàn)了SpringMVC提供的RequestContextHolder,需要的朋友可以參考下
    2023-11-11
  • java中LinkedBlockingQueue與ArrayBlockingQueue的異同

    java中LinkedBlockingQueue與ArrayBlockingQueue的異同

    這篇文章主要介紹了java中LinkedBlockingQueue與ArrayBlockingQueue的異同,需要的朋友可以參考下
    2016-08-08

最新評論