全局異常捕獲處理-@ControllerAdvice+@HandleException


塗塗影院管理系統這個demo中有個異常管理的標簽,用於捕獲 塗塗影院APP用戶異常信息 ,有小伙伴好奇,排除APP,后台端的是如何處理全局異常的,故項目中的實際應用已記之。

關於目前的異常處理

在使用全局異常處理之前,就目前我們是如何處理程序中的異常信息的呢?

throws Exception + try-catch

怎么講?

在我們目前項目中,往往事務發生在 Service 層,因為會牽扯到調用 Dao 跟數據庫打交道,當數據庫操作失敗時,會讓 Service 層拋出運行時異常,Spring 事物管理器就會進行回滾。

Service 拋出異常,那么 Controller 必然要去捕獲,處理異常,所以,try-catch 就出現了。

看一下Service:

public interface ServiceI{
    ## 保存實體的方法
    public Serializable save(Entity entity) throws Exception;
}

看一下Controller的某個調用方法:

@PostMapping(value = "")
public AppResponse add(@RequestBody Entity entity, Errors errors){
    AppResponse resp = new AppResponse();
    try {
        Entity endity = new Entity();
        endity.setXxx();

        ServiceI.save(dog);

        ## 返回數據
        resp.setData(newDog);

    }catch (BusinessException e){
        resp.setFail(e.getMessage());
    }catch (Exception e){
        resp.setFail("操作失敗!");
    }
    return resp;
}

看上去也沒什么別就,但是一個類中出現大面積的 try-catch ,就顯得非常難看且冗余。

如果使用 @ControllerAdvice + @ExceptionHandler 進行全局的 Controller 層異常處理,只要設計得當,就再也不用在 Controller 層進行 try-catch 了。

書寫全局異常處理

1. @ControllerAdvice注解

定義全局異常處理類,@RestControllerAdvice 為 @ResponseBody + @ControllerAdvice

@Slf4j
@RestControllerAdvice
public class RestCtrlExceptionHandler {

}
2. @ExceptionHandler注解

聲明異常處理方法,方法 handleException() 就會處理所有 Controller 層拋出的 Exception 及其子類的異常,這是最基本的用法了。

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleException(Exception e) {

        String errorMsg = "Exception";
        if (e!=null){
            errorMsg = e.getMessage();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }

結合上邊1、2組合一下:

@Slf4j
@RestControllerAdvice
public class RestCtrlExceptionHandler {

    @ExceptionHandler(TmaxException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleXCloudException(TmaxException e) {

        String errorMsg = "Tmax exception";
        if (e!=null){
            errorMsg = e.getMsg();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleException(Exception e) {

        String errorMsg = "Exception";
        if (e!=null){
            errorMsg = e.getMessage();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }
}

看一下 handleXCloudException() 方法

通常我們需要拋出我們自定義異常,而不是一有異常就全部進入 handleException 中,該方法中 TmaxException 即為我們自定義的異常。

@Data
public class TmaxException extends RuntimeException {

    private String msg;

    public TmaxException(String msg){
        super(msg);
        this.msg = msg;
    }
}

這樣,我們就可以在 Controller 中拋出我們定義的異常了,比如:

throw new TmaxException("連接ES失敗,請檢查ES運行狀態");

如果文章有錯的地方歡迎指正,大家互相留言交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:niceyoo


免責聲明!

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



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