異常

如果在請求對映期間發生異常或從請求處理器(例如 @Controller)丟擲異常,DispatcherServlet 會委託給一系列 HandlerExceptionResolver Bean 來解析異常並提供替代處理,通常是錯誤響應。

下表列出了可用的 HandlerExceptionResolver 實現

表 1. HandlerExceptionResolver 實現
HandlerExceptionResolver 描述

SimpleMappingExceptionResolver

異常類名與錯誤檢視名稱之間的對映。適用於在瀏覽器應用中渲染錯誤頁面。

DefaultHandlerExceptionResolver

解析 Spring MVC 丟擲的異常並將其對映到 HTTP 狀態碼。另請參閱替代方案 ResponseEntityExceptionHandler錯誤響應

ResponseStatusExceptionResolver

解析帶有 @ResponseStatus 註解的異常,並根據註解中的值將其對映到 HTTP 狀態碼。

ExceptionHandlerExceptionResolver

透過呼叫 @Controller@ControllerAdvice 類中的 @ExceptionHandler 方法來解析異常。參見 @ExceptionHandler 方法

解析器鏈

您可以在 Spring 配置中宣告多個 HandlerExceptionResolver Bean,並透過設定其 order 屬性來形成異常解析器鏈。order 屬性值越高,異常解析器的位置越靠後。

HandlerExceptionResolver 的約定規定它可以返回

  • 指向錯誤檢視的 ModelAndView

  • 如果在解析器內部處理了異常,則返回空的 ModelAndView

  • 如果異常仍未解決,則返回 null,以便後續解析器嘗試處理;如果異常最終仍未處理,則允許其冒泡到 Servlet 容器。

MVC Config 會自動宣告內建的解析器,用於處理預設的 Spring MVC 異常、帶有 @ResponseStatus 註解的異常以及支援 @ExceptionHandler 方法。您可以自定義或替換這個列表。

容器錯誤頁面

如果任何 HandlerExceptionResolver 都未能解決異常,從而使其繼續傳播,或者如果響應狀態被設定為錯誤狀態(即 4xx、5xx),Servlet 容器可以渲染一個預設的 HTML 錯誤頁面。要自定義容器的預設錯誤頁面,您可以在 web.xml 中宣告錯誤頁面對映。以下示例展示瞭如何做到這一點:

<error-page>
	<location>/error</location>
</error-page>

根據前面的示例,當異常冒泡或響應具有錯誤狀態時,Servlet 容器會在容器內向配置的 URL(例如,/error)發起 ERROR 排程。然後由 DispatcherServlet 對其進行處理,可能會將其對映到 @Controller,該控制器可以實現為返回帶有模型的錯誤檢視名稱,或者渲染 JSON 響應,如下例所示:

  • Java

  • Kotlin

@RestController
public class ErrorController {

	@RequestMapping(path = "/error")
	public Map<String, Object> handle(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<>();
		map.put("status", request.getAttribute("jakarta.servlet.error.status_code"));
		map.put("reason", request.getAttribute("jakarta.servlet.error.message"));
		return map;
	}
}
@RestController
class ErrorController {

	@RequestMapping(path = ["/error"])
	fun handle(request: HttpServletRequest): Map<String, Any> {
		val map = HashMap<String, Any>()
		map["status"] = request.getAttribute("jakarta.servlet.error.status_code")
		map["reason"] = request.getAttribute("jakarta.servlet.error.message")
		return map
	}
}
Servlet API 不提供在 Java 中建立錯誤頁面對映的方法。但是,您可以同時使用 WebApplicationInitializer 和一個最小的 web.xml