springboot 的異常處理
背景分析
在專案的開發中,不管是對底層的資料邏輯操作過程,還是業務邏輯的處理過程,還是控制邏輯的處理過程,都不可避免會遇到各種可預知的、不可預知的異常。處理好異常對系統有很好的保護作用,同時會大大提高使用者的體驗。
異常處理分析
概述
Java專案中處理異常方式無非兩種,要麼執行trycatch操作,要麼執行throw操作(拋給其它物件處理),無論採用哪種方式,其目的是讓我們的系統對異常要有反饋。但現在的問題是我們如何讓這種反饋程式碼的編寫即簡單又直觀、友好。
處理規範
我們在處理異常的過程中通常要遵循一定的設計規範,例如:
- 捕獲異常時與丟擲的異常必須完全匹配,或者捕獲異常是丟擲異常的父類型別。
- 避免直接丟擲RuntimeException,更不允許丟擲Exception或者Throwable,應使用有業務含義的自定義異常(例如ServiceException)。
- 捕獲異常後必須進行處理(例如記錄日誌)。如果不想處理它,需要將異常拋給它的呼叫者。
- 最外層的邏輯必須處理異常,將其轉化成使用者可以理解的內容。
- 避免出現重複的程式碼(Don’t Repeat Yourself),即DAY原則。
SpringBoot 工程下的異常處理
準備工作
第一步:建立專案或module,並新增web依賴,程式碼如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第二步:修改專案訪問埠為80,例如
server.port=80
第三步:定義Controller類,程式碼如下:
package com.cy.pj.arithmetic.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ArithmeticController {
@RequestMapping("doCompute/{n1}/{n2}")
@ResponseBody
public String doCompute(@PathVariable Integer n1,
@PathVariable Integer n2){
Integer result=n1/n2;
return "Result is "+result;
}
}
第四步啟動專案進行訪問測試
在瀏覽器位址列輸入http://localhost/doCompute/10/2,檢測輸出結果。
Resultis5
預設異常處理
在瀏覽器位址列輸入http://localhost/doCompute/10/0,檢測輸出結果。
對於這樣的預設異常處理(spring boot提供),使用者體驗不太友好,為了呈現更加友好的異常資訊,我們通常要對異常進行自定義處理。
自己try異常處理
在控制層方法中,我們可以進行try catch處理,例如:
@RequestMapping("doCompute/{n1}/{n2}")
@ResponseBody
public String doCompute(@PathVariable Integer n1,
@PathVariable Integer n2){
try{
Integer result=n1/n2;
return "Result is "+result;
}catch(ArithmeticException e){
return "exception is "+e.getMessage();
}
}
一個Controller類中通常會有多個方法,這樣多個方法中都寫try語句進行異常處理會帶來大量重複程式碼的編寫,不易維護。
Controller內部定義異常處理方法
在Controller類中新增異常處理方法,程式碼如下:
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public String doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
return "計算過程中出現了異常,異常資訊為"+e.getMessage();
}
@ExceptionHandler註解描述的方法為異常處理方法(註解中的異常型別為可處理的異常型別),假如Controller類中的邏輯方法中出現異常後沒有處理異常,則會查詢Controller類中有沒有定義異常處理方法,假如定義了,且可以處理丟擲的異常型別,則由異常處理方法處理異常。
控制層中的全域性異常處理類及方法定義
當專案由多個控制層類中有多個共性異常的處理方法定義時,我們可以將這些方法提取到公共的父類物件中,但是這種方式是一種強耦合的實現,不利於程式碼的維護。我們還可以藉助spring框架中web模組定義的全域性異常處理規範進行實現,例如定義全域性異常處理類,程式碼如下:
package com.cy.pj.common.web;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public String doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
return "計算過程中出現了異常,異常資訊為"+e.getMessage();
}
}
其中,@RestControllerAdvice 註解描述的類為全域性異常處理類,當控制層方法中的異常沒有自己捕獲,也沒有定義其內部的異常處理方法,底層預設會查詢全域性異常處理類,呼叫對應的異常處理方法進行異常處理。如圖所示:
總結(Summary)
本小節主要是對springboot中的異常處理機制進行了簡單分析和講解。目的是掌握springboot工程下的異常處理方式,並基於業務的不同進行響應的異常處理。從而有效提高其使用者體驗,加強系統的容錯能力。