SpringBoot實戰 之 異常處理篇

2022-06-24 13:03:09 字數 3192 閱讀 5946

在網際網路時代,我們所開發的應用大多是直面使用者的,程式中的任何一點小疏忽都可能導致使用者的流失,而程式出現異常往往又是不可避免的,那該如何減少程式異常對使用者體驗的影響呢?其實方法很簡單,對異常進行捕獲,然後給予相應的處理即可。但實現的方式卻有好多種,例如:

try  catch (exception e)
像這種標準的 try-catch 是可以解決問題,但如果讓你在每個介面實現裡面都 try-catch 一下,我想你應該是不太願意的。那麼下面來介紹下 springboot 為我們提供的處理方式。

首先,我們來模擬一下,出現異常的場景,方式比較簡單,直接在正常的**裡面丟擲乙個異常即可。

在上面的示例中,呼叫介面時,出現了異常,但客戶端卻收到乙個相對正常的響應,這是因為 springboot 預設提供了乙個 /error 的對映,該對映被註冊為 servlet 容器中的乙個全域性錯誤頁面用來合理處理所有的異常情況。但示例中的響應報文不符合我們定義的資料規範,想要使其滿足自己的資料規範,可以自己定義乙個新的 errorcontroller,**如下:

@controller

public class fundaerrorcontroller implements errorcontroller

@responsebody

public result dohandleerror()

}

當我們再次訪問該介面的時候會返回:

熟悉 springmvc 的人應該都知道 @exceptionhandler 這個註解,在 springboot 裡面,我們同樣可以使用它來做異常捕獲。

這種方式使用場景較少,但作為學習 @exceptionhandler 入門示例還是非常不錯的,直接在對應的 controller 裡面增加乙個異常處理的方法,並使用 @exceptionhandler 標識它即可。

客戶端得到的效果與使用 errorcontroller 完全一致,但對於服務端來說卻不太一樣,如果仔細觀察這兩種方式的日誌輸出的話,會發現使用 errorcontroller 時,後台會列印出異常堆疊資訊,而使用 @exceptionhandler 卻不會,這是因為這兩種處理方式的流程存在著本質的差別。

errorcontroller:呼叫 usercontroller 丟擲異常時,自身沒有做任何處理,所以會列印出堆疊資訊,但這個異常會被 servlet 容器捕捉到,servlet 容器再將請求**給註冊好的異常處理對映 /error 做處理,客戶端收到的實際是 errorcontroller 的處理結果,而不是 usercontroller 的。

exceptionhandler:異常的處理方法直接被定義在 usercontroller 裡面,也就是說,在異常丟擲的時候,usercontroller 會使用自己的方法去做異常處理,而不會丟擲給 servlet 容器,所以這個地方沒有列印堆疊資訊。

如果想要在後台新增堆疊資訊的輸出也非常簡單,只需要將該異常作為乙個引數傳遞給異常處理方法,然後在處理方法裡面做相應的操作即可。

@exceptionhandler(exception.class)

public result handleexception(exception e)

專案的往往存在著多個 controller,而它們在異常處理方面有存在著很多的共性,這樣就不太適合在每乙個 controller 裡面都編寫乙個對應的異常處理方法。可以將異常處理方法向上挪移到父類中,然後所有的 controller 統一繼承父類即可。

定義父類 basecontroller:

public class basecontroller 

}

usercontroller 通過繼承 basecontroller 完成異常處理:

@restcontroller

public class usercontroller extends basecontroller

對於使用父級 controller 完成異常處理也有著它自己的缺點,那就是**耦合嚴重,一旦哪天忘記繼承 basecontroller,異常又會直達客戶了。想要解除這種耦合關係,可以使用 @controlleradvice 來協助處理。

@controlleradvice

@responsebody

public class exceptionhandleradvice

}

實際的開發場景中,異常是區分很多類別的,不同類別的異常需要給使用者不同的反饋。例如,在 springboot實戰 之 資料互動篇 中有使用到註解式引數校驗,但校驗不通過原因並沒有以有效的方式告之給前端應用。下面我們通過上面提到的異常處理方式來完成這個功能:

首先,在 resultcode 類中定義好 引數錯誤 的 code,**如下:

parameter_error(10101, "引數錯誤")
在 exceptionhandleradvice 中新增對應的異常處理方法:

@exceptionhandler(methodargumentnotvalidexception.class)

public result handleillegalparamexception(methodargumentnotvalidexception e)

result result = new result(resultcode.parameter_error);

result.setmsg(tips);

return result;

}

當應用程式丟擲 methodargumentnotvalidexception 時,會精確匹配到該方法,在方法裡面會獲取到校驗結果,並將所有校驗錯誤中的第一條返回給前端應用。

這樣的話,就可以在 exceptionhandleradvice 裡面新增各種各樣的異常處理方法,以適合不同的應用場景。

SpringBoot之統一異常處理

異常,不僅僅是程式執行狀態的描述,還可以使得 編寫更加的規範 1 自定義異常 fieldvalueinvalidexception package com.geniuses.sewage zero straight.exception import com.geniuses.sewage zero ...

Spring Boot功能實戰

新增了spring boot基礎依賴後,如要使用web mvc功能,只需要新增如下啟動器即可,spring boot會自動裝配web功能。org.springframework.bootgroupid spring boot starter webartifactid dependency depe...

springBoot異常處理

使得訪問 exception一定會產生異常 some exception controller public class exceptioncontroller return hello 再寫個全域性異常處理類 controlleradvice public class globalexceptio...