例外狀況

如果請求映射期間發生例外狀況,或從請求處理器 (例如 @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 設定 會自動為預設 Spring MVC 例外狀況、@ResponseStatus 註解的例外狀況以及對 @ExceptionHandler 方法的支援宣告內建解析器。您可以自訂該列表或替換它。

容器錯誤頁面

如果任何 HandlerExceptionResolver 仍未解析例外狀況,因此讓它傳播,或者如果回應狀態設定為錯誤狀態 (即 4xx、5xx),Servlet 容器可以在 HTML 中呈現預設錯誤頁面。若要自訂容器的預設錯誤頁面,您可以在 web.xml 中宣告錯誤頁面映射。以下範例說明如何執行此操作

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

以上述範例為例,當例外狀況冒泡或回應具有錯誤狀態時,Servlet 容器會在容器內對已配置的 URL (例如 /error) 進行 ERROR 分派。然後由 DispatcherServlet 處理,可能會將其映射到 @Controller,可以實作該 @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