异常

@Controller@ControllerAdvice类可以具有@ExceptionHandler方法处理来自 Controller 方法的异常,如下例所示: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

对于匹配的异常类型,最好将目标异常声明为方法参数, 如前面的示例所示。当多个异常方法匹配时,根异常匹配为 通常优先于 Cause 异常匹配。更具体地说,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变体,该方法通常使用 实际的FileSystemExceptionRemoteExceptioninstance 作为参数, 由于它们都从IOException.但是,如果有任何此类匹配 exception 在包装器 exception 中传播,该 exception 本身是一个IOException, 传入的 Exception 实例是该包装器 Exception。spring-doc.cadn.net.cn

handle(Exception)变体。这是 always 调用时,在 wrapping 场景中使用 wrapper 异常调用,并且 实际匹配异常ex.getCause()在那种情况下。 传入的异常是实际的FileSystemExceptionRemoteException实例。spring-doc.cadn.net.cn

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

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

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

支持@ExceptionHandler方法构建在DispatcherServlet级别、HandlerExceptionResolver 机制。spring-doc.cadn.net.cn

媒体类型映射

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

对于相同的异常类型,应用程序可以直接在 Comments 上声明可制作的媒体类型: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 错误视图。 每@ExceptionHandlerannotation 可以声明几种可制作的媒体类型, 错误处理阶段的内容协商将决定将使用哪种内容类型。spring-doc.cadn.net.cn

方法参数

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

Method 参数 描述

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

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

HandlerMethodspring-doc.cadn.net.cn

用于访问引发异常的 controller 方法。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

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

HttpMethodspring-doc.cadn.net.cn

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

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

当前请求区域设置,由最具体的LocaleResolveravailable — 在 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

对于任何 session 属性的访问,与存储在 session 作为类级别@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

ErrorResponsespring-doc.cadn.net.cn

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

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实例,用于与隐式模型一起进行渲染 — determined 通过 Command Objects 和@ModelAttribute方法。handler 方法还可以 通过声明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

要使用的 view 和 model 属性,以及响应状态(可选)。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 确定), 默认情况下,它被视为要添加到模型的 model 属性。如果是简单类型, 它仍然没有解决。spring-doc.cadn.net.cn