此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

异常

@Controller并且@ControllerAdvice类可以有@ExceptionHandler处理来自控制器方法的异常的方法,如以下示例所示:spring-doc.cadn.net.cn

import java.io.IOException;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;

@Controller
public class SimpleController {

	@ExceptionHandler(IOException.class)
	public ResponseEntity<String> handle() {
		return ResponseEntity.internalServerError().body("Could not read file storage");
	}

}
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ExceptionHandler
import java.io.IOException

@Controller
class SimpleController {

	@ExceptionHandler(IOException::class)
	fun handle() : ResponseEntity<String> {
		return ResponseEntity.internalServerError().body("Could not read file storage")
	}
	
}

异常映射

异常可能与正在传播的顶级异常(例如,直接IOException被抛出)或针对包装异常中的嵌套原因(例如, 一IOException包裹在一个IllegalStateException).从 5.3 开始,这可以匹配 在任意原因水平上,而以前只考虑直接原因。spring-doc.cadn.net.cn

对于匹配的异常类型,最好将目标异常声明为方法参数, 如前面的示例所示。当多个异常方法匹配时,根异常匹配为 通常优先于原因异常匹配。更具体地说,ExceptionDepthComparator用于根据抛出异常类型的异常深度对异常进行排序。spring-doc.cadn.net.cn

或者,注释声明可以缩小异常类型以匹配 如以下示例所示:spring-doc.cadn.net.cn

@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handleIoException(IOException ex) {
	return ResponseEntity.internalServerError().body(ex.getMessage());
}
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handleIoException(ex: IOException): ResponseEntity<String> {
	return ResponseEntity.internalServerError().body(ex.message)
}

您甚至可以使用具有非常通用的参数签名的特定异常类型的列表, 如以下示例所示:spring-doc.cadn.net.cn

@ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handleExceptions(Exception ex) {
	return ResponseEntity.internalServerError().body(ex.getMessage());
}
@ExceptionHandler(FileSystemException::class, RemoteException::class)
fun handleExceptions(ex: Exception): ResponseEntity<String> {
	return ResponseEntity.internalServerError().body(ex.message)
}

根异常匹配和原因异常匹配之间的区别可能令人惊讶。spring-doc.cadn.net.cn

IOException变体,该方法通常使用 实际的FileSystemExceptionRemoteException实例作为参数, 由于它们都从IOException.但是,如果有任何此类匹配 异常在包装器异常中传播,该异常本身是一个IOException, 传入的异常实例就是该包装异常。spring-doc.cadn.net.cn

handle(Exception)变体。这是 在包装场景中始终与包装器异常一起调用,使用 实际匹配异常要通过ex.getCause()在这种情况下。 传入的异常是实际的FileSystemExceptionRemoteException仅当这些作为顶级异常抛出时,实例。spring-doc.cadn.net.cn

我们通常建议您在参数签名中尽可能具体, 减少根异常类型和原因异常类型之间不匹配的可能性。 考虑将多匹配方法分解为单独的@ExceptionHandler方法,每个方法都通过其签名匹配单个特定的异常类型。spring-doc.cadn.net.cn

在多@ControllerAdvice安排,我们建议声明您的主根例外 映射@ControllerAdvice以相应的顺序优先。虽然根 异常匹配优先于原因,这是在给定方法中定义的 controller 或@ControllerAdvice类。这意味着优先级更高的原因匹配@ControllerAdvicebean 优先于优先级较低的任何匹配项(例如,root)@ControllerAdvice豆。spring-doc.cadn.net.cn

最后但并非最不重要的一点是,一个@ExceptionHandler方法实现可以选择支持 通过以原始形式重新抛出给定的异常实例来处理它。 这在您只对根级匹配感兴趣或 在无法静态确定的特定上下文中的匹配项。重新投掷 异常通过剩余的解析链传播,就好像 给定的@ExceptionHandler方法一开始就不匹配。spring-doc.cadn.net.cn

@ExceptionHandlerSpring MVC 中的方法构建在DispatcherServlet级别,HandlerExceptionResolver 机制。spring-doc.cadn.net.cn

媒体类型映射

除了异常类型之外,@ExceptionHandler方法还可以声明可生产的媒体类型。 这允许根据 HTTP 客户端请求的媒体类型(通常在“接受”HTTP 请求标头中)优化错误响应。spring-doc.cadn.net.cn

对于相同的异常类型,应用程序可以直接在批注上声明可生成的媒体类型:spring-doc.cadn.net.cn

@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
	return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}

@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
	model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
	return "errorView";
}
@ExceptionHandler(produces = ["application/json"])
fun handleJson(exc: IllegalArgumentException): ResponseEntity<ErrorMessage> {
	return ResponseEntity.badRequest().body(ErrorMessage(exc.message, 42))
}

@ExceptionHandler(produces = ["text/html"])
fun handle(exc: IllegalArgumentException, model: Model): String {
	model.addAttribute("error", ErrorMessage(exc.message, 42))
	return "errorView"
}

在这里,方法处理相同的异常类型,但不会作为重复项被拒绝。 相反,请求“application/json”的 API 客户端将收到 JSON 错误,浏览器将收到 HTML 错误视图。 每@ExceptionHandler注释可以声明几种可生产的媒体类型, 错误处理阶段的内容协商将决定将使用哪种内容类型。spring-doc.cadn.net.cn

方法参数

@ExceptionHandler方法支持以下参数:spring-doc.cadn.net.cn

方法参数 描述

异常类型spring-doc.cadn.net.cn

用于访问引发的异常。spring-doc.cadn.net.cn

HandlerMethodspring-doc.cadn.net.cn

用于访问引发异常的控制器方法。spring-doc.cadn.net.cn

WebRequest,NativeWebRequestspring-doc.cadn.net.cn

对请求参数以及请求和会话属性的通用访问,无需直接 使用 Servlet API。spring-doc.cadn.net.cn

jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponsespring-doc.cadn.net.cn

选择任何特定的请求或响应类型(例如,ServletRequestHttpServletRequest或 Spring 的MultipartRequestMultipartHttpServletRequest).spring-doc.cadn.net.cn

jakarta.servlet.http.HttpSessionspring-doc.cadn.net.cn

强制存在会话。因此,这样的论点从来都不是null.
请注意,会话访问不是线程安全的。考虑将
RequestMappingHandlerAdapter实例的synchronizeOnSessionflag 到true如果多个 允许请求并发访问会话。spring-doc.cadn.net.cn

java.security.Principalspring-doc.cadn.net.cn

当前经过身份验证的用户 — 可能是特定的Principal实现类(如果已知)。spring-doc.cadn.net.cn

HttpMethodspring-doc.cadn.net.cn

请求的 HTTP 方法。spring-doc.cadn.net.cn

java.util.Localespring-doc.cadn.net.cn

当前请求区域设置,由最具体的LocaleResolver可用 — 在 effect,则配置的LocaleResolverLocaleContextResolver.spring-doc.cadn.net.cn

java.util.TimeZone,java.time.ZoneIdspring-doc.cadn.net.cn

与当前请求关联的时区,由LocaleContextResolver.spring-doc.cadn.net.cn

java.io.OutputStream,java.io.Writerspring-doc.cadn.net.cn

用于访问原始响应正文,如 Servlet API 公开的那样。spring-doc.cadn.net.cn

java.util.Map,org.springframework.ui.Model,org.springframework.ui.ModelMapspring-doc.cadn.net.cn

用于访问模型以进行错误响应。总是空的。spring-doc.cadn.net.cn

RedirectAttributesspring-doc.cadn.net.cn

指定在重定向时要使用的属性 — (即要附加到查询中 string)和 flash 属性,以临时存储,直到重定向后的请求。 请参阅重定向属性Flash 属性spring-doc.cadn.net.cn

@SessionAttributespring-doc.cadn.net.cn

为了访问任何会话属性,与存储在 会话作为类级别的结果@SessionAttributes声明。 看@SessionAttribute了解更多详情。spring-doc.cadn.net.cn

@RequestAttributespring-doc.cadn.net.cn

用于访问请求属性。看@RequestAttribute了解更多详情。spring-doc.cadn.net.cn

返回值

@ExceptionHandler方法支持以下返回值:spring-doc.cadn.net.cn

返回值 描述

@ResponseBodyspring-doc.cadn.net.cn

返回值通过HttpMessageConverter实例并写入 响应。看@ResponseBody.spring-doc.cadn.net.cn

HttpEntity<B>,ResponseEntity<B>spring-doc.cadn.net.cn

返回值指定完整响应(包括 HTTP 标头和正文) 通过HttpMessageConverter实例并写入响应。 请参阅 ResponseEntityspring-doc.cadn.net.cn

ErrorResponse,ProblemDetailspring-doc.cadn.net.cn

要呈现 RFC 9457 错误响应,并在正文中包含详细信息, 请参阅错误响应spring-doc.cadn.net.cn

Stringspring-doc.cadn.net.cn

要解析的视图名称ViewResolver实现并与 隐式模型 — 通过命令对象和@ModelAttribute方法。 处理程序方法还可以通过声明Model参数(前面描述)。spring-doc.cadn.net.cn

Viewspring-doc.cadn.net.cn

一个View用于与隐式模型一起渲染的实例 — 确定 通过命令对象和@ModelAttribute方法。处理程序方法还可以 通过声明Model参数(前面描述)。spring-doc.cadn.net.cn

java.util.Map,org.springframework.ui.Modelspring-doc.cadn.net.cn

要添加到隐式模型的属性,其中隐式确定了视图名称 通过RequestToViewNameTranslator.spring-doc.cadn.net.cn

@ModelAttributespring-doc.cadn.net.cn

要添加到模型中的属性,视图名称通过 一个RequestToViewNameTranslator.spring-doc.cadn.net.cn

请注意@ModelAttribute是可选的。请参阅末尾的“任何其他返回值” 这个表。spring-doc.cadn.net.cn

ModelAndView对象spring-doc.cadn.net.cn

要使用的视图和模型属性,以及响应状态(可选)。spring-doc.cadn.net.cn

voidspring-doc.cadn.net.cn

具有void返回类型(或null返回值)被认为完全具有 如果响应也有ServletResponseOutputStream参数,或 一个@ResponseStatus注解。如果控制器已进行正ETaglastModified时间戳检查(有关详细信息,请参阅控制器)。spring-doc.cadn.net.cn

如果以上都不是真的,则void返回类型还可以指示 REST 控制器或 HTML 控制器的默认视图名称选择。spring-doc.cadn.net.cn

任何其他返回值spring-doc.cadn.net.cn

如果返回值与上述任何一项都不匹配,并且不是简单类型(由 BeanUtils#isSimpleProperty 确定), 默认情况下,它被视为要添加到模型中的模型属性。如果是简单类型, 它仍然没有解决。spring-doc.cadn.net.cn