Exceptions

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

Table 1. HandlerExceptionResolver implementations
HandlerExceptionResolver Description

SimpleMappingExceptionResolver

异常类名与错误视图名的映射。对在浏览器应用程序中呈现错误页面非常有用。

DefaultHandlerExceptionResolver

解析 Spring MVC 引发的异常,并将它们映射到 HTTP 状态代码。另见替代项 `ResponseEntityExceptionHandler`和 Error Responses

ResponseStatusExceptionResolver

解析带 @ResponseStatus 注解的异常,并将它们根据注解中的值映射到 HTTP 状态代码。

ExceptionHandlerExceptionResolver

通过在 @Controller@ControllerAdvice 类中调用 @ExceptionHandler 方法来解决异常。请参见 @ExceptionHandler methods

Chain of Resolvers

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

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

  • 一个指向错误视图的 ModelAndView

  • 如果异常在解析机制内被处理,则返回一个空的 ModelAndView

  • null 如果异常仍然未解决,则供后续解析尝试解决;并且,如果异常到最后仍然存在,则允许它冒泡至 Servlet 容器。

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

Container Error Page

如果一个异常未被任何 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