前言
在開發 Web 應用程序時,異常處理是一個至關重要的部分。Spring Boot 提供了一套強大的異常處理機制,使得開發者能夠輕松地處理和響應各種異常情況。本文將深入探討 Spring Boot 中的異常處理機制,包括默認的錯誤處理規則、定制錯誤處理邏輯以及異常處理的自動配置原理。
一、默認錯誤處理規則
在默認情況下,Spring Boot 提供了 /error
路徑來處理所有錯誤的映射。當應用程序發生異常時,Spring Boot 會自動將請求路由到這個默認的錯誤處理路徑。
對于機器客戶端(如 API 調用),Spring Boot 會生成一個 JSON 響應,其中包含錯誤的狀態碼(HTTP 狀態)和異常消息的詳細信息。以下是一個示例 JSON 響應:
{"timestamp": "2024-07-19T08:22:25.669+00:00","status": 404,"error": "Not Found","message": "No message available","path": "/asadada"
}
對于瀏覽器客戶端,Spring Boot 會響應一個“whitelabel”錯誤視圖,以 HTML 格式呈現相同的數據。這個默認的錯誤頁面雖然簡單,但能提供基本的錯誤信息。
二、定制錯誤處理邏輯
1. 自定義錯誤頁
我們可以創建自定義的錯誤頁面來替換默認的“whitelabel”錯誤視圖。例如,創建 error/404.html
和 error/5xx.html
文件,Spring Boot 會根據不同的 HTTP 狀態碼自動選擇對應的錯誤頁面進行渲染。
2. 使用 @ControllerAdvice
和 @ExceptionHandler
通過實現 ErrorController
并注冊該類型的 Bean 定義,或者添加 ErrorAttributes
類型的組件,我們可以完全替換默認的錯誤處理行為。更常見和靈活的方式是使用 @ControllerAdvice
和 @ExceptionHandler
注解。
以下是一個示例代碼:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {// 可以在這里記錄異常日志String errorMessage = "An unexpected error occurred: " + ex.getMessage();return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);}@ExceptionHandler(NotFoundException.class)public ResponseEntity<Object> handleNotFoundException(NotFoundException ex, WebRequest request) {String errorMessage = "Resource not found: " + ex.getMessage();return new ResponseEntity<>(errorMessage, HttpStatus.NOT_FOUND);}
}
在上述代碼中,@ControllerAdvice
注解表示這是一個全局的異常處理器。@ExceptionHandler
注解用于指定處理特定類型異常的方法。當發生 Exception
類型的異常時,handleAllExceptions
方法會被調用;當發生 NotFoundException
類型的異常時,handleNotFoundException
方法會被調用。
3. 實現 HandlerExceptionResolver
我們還可以通過實現 HandlerExceptionResolver
接口來自定義異常處理邏輯。這個接口定義了一個 resolveException
方法,我們可以在這個方法中處理異常并返回一個 ModelAndView
對象。
以下是一個簡單的示例:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// 處理異常邏輯ModelAndView modelAndView = new ModelAndView("error/500");modelAndView.addObject("errorMessage", ex.getMessage());return modelAndView;}
}
三、異常處理自動配置原理
Spring Boot 通過 ErrorMvcAutoConfiguration
類自動配置異常處理規則。在這個配置類中,定義了多個組件:
DefaultErrorAttributes
:實現了ErrorAttributes
和HandlerExceptionResolver
接口,用于收集和提供錯誤屬性信息。BasicErrorController
:處理/error
路徑的請求,根據請求的類型(HTML 或 JSON)返回相應的錯誤響應。BeanNameViewResolver
:視圖解析器,按照返回的視圖名作為組件的 id 去容器中找視圖對象。DefaultErrorViewResolver
:如果發生錯誤,會以 HTTP 的狀態碼作為視圖頁地址(viewName),找到真正的頁面。
以下是 ErrorMvcAutoConfiguration
類中部分組件的定義示例:
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
@ConditionalOnClass(EmbeddedWebApplication.class)
public class ErrorMvcAutoConfiguration {// 定義 DefaultErrorAttributes@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();}// 定義 BasicErrorController@Bean@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider<ErrorViewResolver> errorViewResolvers) {return new BasicErrorController(errorAttributes, errorViewResolvers.orderedStream().collect(Collectors.toList()));}// 其他組件定義...
}
四、異常處理步驟流程
- 執行目標方法:當目標方法運行期間發生任何異常時,會被
catch
,并且標志當前請求結束,使用dispatchException
進入視圖解析流程(頁面渲染?)。 - 調用
processDispatchResult
方法:該方法處理派發結果,包括處理異常。 - 處理
HandlerException
:遍歷所有的handlerExceptionResolvers
,看誰能處理當前異常。
系統默認的異常解析器包括 DefaultErrorAttributes
、HandlerExceptionResolverComposite
等。DefaultErrorAttributes
先來處理異常,把異常信息保存到 request
域,并且返回 null
。如果沒有任何人能處理異常,異常會被拋出,最終由底層的 BasicErrorController
處理,解析錯誤視圖。
總結
Spring Boot 的異常處理機制提供了靈活且強大的方式來處理應用程序中的各種異常情況。通過默認的錯誤處理規則、定制錯誤處理邏輯以及理解異常處理的自動配置原理,我們可以更好地構建健壯的 Web 應用程序。在實際開發中,根據具體的需求選擇合適的異常處理方式,能夠提高應用程序的穩定性和用戶體驗。