Exceptions

如果在请求映射或请求处理程序(例如 @Controller)中发生了异常,DispatcherServlet 会将其委托给一个 HandlerExceptionResolver bean 的链条以解决该异常并提供备用处理,通常是一个错误响应。

If an exception occurs during request mapping or is thrown from a request handler (such as a @Controller), the DispatcherServlet delegates to a chain of HandlerExceptionResolver beans to resolve the exception and provide alternative handling, which is typically an error response.

下表列出了可供使用的 HandlerExceptionResolver 实现:

The following table lists the available HandlerExceptionResolver implementations:

Table 1. HandlerExceptionResolver implementations
HandlerExceptionResolver Description

SimpleMappingExceptionResolver

A mapping between exception class names and error view names. Useful for rendering error pages in a browser application.

DefaultHandlerExceptionResolver

Resolves exceptions raised by Spring MVC and maps them to HTTP status codes. See also alternative ResponseEntityExceptionHandler and Error Responses.

ResponseStatusExceptionResolver

Resolves exceptions with the @ResponseStatus annotation and maps them to HTTP status codes based on the value in the annotation.

ExceptionHandlerExceptionResolver

Resolves exceptions by invoking an @ExceptionHandler method in a @Controller or a @ControllerAdvice class. See @ExceptionHandler methods.

Chain of Resolvers

你可以通过在你的 Spring 配置中声明多个 HandlerExceptionResolver bean 并根据需要设置它们的 order 属性来形成一个异常解析器链。顺序属性越高,异常解析器的位置越靠后。

You can form an exception resolver chain by declaring multiple HandlerExceptionResolver beans in your Spring configuration and setting their order properties as needed. The higher the order property, the later the exception resolver is positioned.

HandlerExceptionResolver 的契约规定它可以返回:

The contract of HandlerExceptionResolver specifies that it can return:

  • a ModelAndView that points to an error view.

  • An empty ModelAndView if the exception was handled within the resolver.

  • null if the exception remains unresolved, for subsequent resolvers to try, and, if the exception remains at the end, it is allowed to bubble up to the Servlet container.

MVC Config自动声明用于默认 Spring MVC 异常、用于`@ResponseStatus`注释的异常以及用于支持`@ExceptionHandler`方法的内置解析器。可以自定义该列表或替换它。

The MVC Config automatically declares built-in resolvers for default Spring MVC exceptions, for @ResponseStatus annotated exceptions, and for support of @ExceptionHandler methods. You can customize that list or replace it.

Container Error Page

如果一个异常未被任何 HandlerExceptionResolver 解决,因此没有传播出去,或者如果响应状态设置为错误状态(即 4xx、5xx),Servlet 容器会在 HTML 中呈现一个默认错误页面。要自定义容器的默认错误页面,你可以在 web.xml 中声明一个错误页面映射。以下示例展示了如何做到这一点:

If an exception remains unresolved by any HandlerExceptionResolver and is, therefore, left to propagate or if the response status is set to an error status (that is, 4xx, 5xx), Servlet containers can render a default error page in HTML. To customize the default error page of the container, you can declare an error page mapping in web.xml. The following example shows how to do so:

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

在前一个示例中,当一个异常冒出或响应具有错误状态时,Servlet 容器会在容器内向配置的 URL(例如 error)执行 ERROR 调度。然后由 DispatcherServlet 处理它,它可能将其映射到一个 @Controller,该 @Controller 可以实现为返回带有模型的错误视图名称或呈现 JSON 响应,如下面的示例所示:

Given the preceding example, when an exception bubbles up or the response has an error status, the Servlet container makes an ERROR dispatch within the container to the configured URL (for example, /error). This is then processed by the DispatcherServlet, possibly mapping it to a @Controller, which could be implemented to return an error view name with a model or to render a JSON response, as the following example shows:

  • 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

The Servlet API does not provide a way to create error page mappings in Java. You can, however, use both a WebApplicationInitializer and a minimal web.xml.