SpringBoot實戰之異常處理篇

來源:互聯網
上載者:User

標籤:類別   報文   tty   int   def   關係   應用程式   ror   value   

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

try {

...} catch (Exception e) {
doSomeThing();
}

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

1. ErrorController 應用

首先,我們來類比一下,出現異常的情境,方式比較簡單,直接在正常的代碼裡面拋出一個異常即可。

在上面的樣本中,調用介面時,出現了異常,但用戶端卻收到一個相對正常的響應,這是因為 SpringBoot 預設提供了一個 /error 的映射,該映射被註冊為 Servlet 容器中的一個全域錯誤頁面用來合理處理所有的異常情況。但樣本中的響應報文不符合我們定義的資料規範,想要使其滿足自己的資料規範,可以自己定義一個新的 ErrorController,代碼如下:

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class FundaErrorController implements ErrorController
{


@Override
public String getErrorPath() {
return "/error";
}

@RequestMapping
@ResponseBody
public Result doHandleError() {
return new Result(ResultCode.WEAK_NET_WORK);
}
}

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

{
"code": -1,
"msg": "網路異常,請稍後重試",
"data": null
}
2. ExceptionHandler 應用

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

2.1. 單一 Controller 異常處理

這種方式使用情境較少,但作為學習 @ExceptionHandler 入門樣本還是非常不錯的,直接在對應的 Controller 裡面增加一個異常處理的方法,並使用 @ExceptionHandler 標識它即可。

@ExceptionHandler(Exception.class)
public Result handleException() {
return new Result(ResultCode.WEAK_NET_WORK);
}

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

  1. ErrorController: 調用 UserController 拋出異常時,自身沒有做任何處理,所以會列印出堆棧資訊,但這個異常會被 Servlet 容器捕捉到,Servlet 容器再將請求轉寄給註冊好的異常處理映射 /error 做處理,用戶端收到的實際是 ErrorController 的處理結果,而不是 UserController 的。

  2. ExceptionHandler: 異常的處理方法直接被定義在 UserController 裡面,也就是說,在異常拋出的時候,UserController 會使用自己的方法去做異常處理,而不會拋出給 Servlet 容器,所以這個地方沒有列印堆棧資訊。

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

@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
e.printStackTrace();
return new Result(ResultCode.WEAK_NET_WORK);
}
2.2. 父級 Controller 異常處理

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

定義父類 BaseController:

public class BaseController {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
e.printStackTrace();
return new Result(ResultCode.WEAK_NET_WORK);
}
}

UserController 通過繼承 BaseController 完成異常處理:

@RestController
@RequestMapping("/sys/user")
public class UserController extends BaseController {
...}
2.3. Advice 異常處理

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

@ControllerAdvice
@ResponseBody
public class ExceptionHandlerAdvice {

@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
e.printStackTrace();
return new Result(ResultCode.WEAK_NET_WORK);
}

}
3. 多類別異常處理

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

首先,在 ResultCode 類中定義好 參數錯誤 的 code,代碼如下:

PARAMETER_ERROR(10101, "參數錯誤")

在 ExceptionHandlerAdvice 中添加對應的異常處理方法:

@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleIllegalParamException(MethodArgumentNotValidException e) {
List<ObjectError> errors = e.getBindingResult().getAllErrors();
String tips = "參數不合法";
if (errors.size() > 0) {
tips = errors.get(0).getDefaultMessage();
}
Result result = new Result(ResultCode.PARAMETER_ERROR);
result.setMsg(tips);
return result;
}

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

這樣的話,就可以在 ExceptionHandlerAdvice 裡面添加各種各樣的異常處理方法,以適合不同的應用情境。

項目的 github 地址:https://github.com/qchery/funda

SpringBoot實戰之異常處理篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.