此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
异常
@Controller
@ControllerAdvice类可以具有@ExceptionHandler
方法处理来自 Controller 方法的异常,如下例所示:
-
Java
-
Kotlin
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 开始,这可以匹配
在任意原因水平上,而以前只考虑直接原因。
对于匹配的异常类型,最好将目标异常声明为方法参数,
如前面的示例所示。当多个异常方法匹配时,根异常匹配为
通常优先于 Cause 异常匹配。更具体地说,ExceptionDepthComparator
用于根据异常从引发的异常类型中对异常的深度对异常进行排序。
或者,注释声明可以缩小异常类型的范围以匹配 如下例所示:
-
Java
-
Kotlin
@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)
}
您甚至可以使用具有非常通用参数签名的特定异常类型列表 如下例所示:
-
Java
-
Kotlin
@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)
}
根异常匹配和原因异常匹配之间的区别可能令人惊讶。 在 在 |
我们通常建议您在参数签名中尽可能具体。
减少 root 和 cause 异常类型之间不匹配的可能性。
考虑将多重匹配方法拆分为单独的@ExceptionHandler
方法,每个方法都通过其签名匹配单个特定的异常类型。
在多@ControllerAdvice
安排中,我们建议声明您的主根例外
mappings 在@ControllerAdvice
prioritizeed 和相应的顺序。虽然 root
exception match 优先于 cause,这是在给定
controller 或@ControllerAdvice
类。这意味着优先级更高的原因匹配@ControllerAdvice
bean 优先于优先级较低的任何匹配项(例如 root)@ControllerAdvice
豆。
最后但并非最不重要的一点是,一个@ExceptionHandler
方法实现可以选择 back
通过以原始形式重新引发给定的异常实例来处理该实例。
这在您只对根级别匹配或
无法静态确定的特定上下文中的匹配项。一个 rethrown
exception 通过剩余的解析链传播,就像
给定的@ExceptionHandler
method 一开始就不匹配。
支持@ExceptionHandler
方法构建在DispatcherServlet
级别、HandlerExceptionResolver 机制。
媒体类型映射
除了异常类型之外,@ExceptionHandler
方法还可以声明可制作的媒体类型。
这允许根据 HTTP 客户端请求的媒体类型(通常在 “Accept” HTTP 请求标头中)来优化错误响应。
对于相同的异常类型,应用程序可以直接在 Comments 上声明可制作的媒体类型:
-
Java
-
Kotlin
@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
annotation 可以声明几种可制作的媒体类型,
错误处理阶段的内容协商将决定将使用哪种内容类型。
方法参数
@ExceptionHandler
方法支持以下参数:
Method 参数 | 描述 |
---|---|
异常类型 |
用于访问引发的异常。 |
|
用于访问引发异常的 controller 方法。 |
|
对请求参数以及请求和会话属性的通用访问,无需直接 使用 Servlet API。 |
|
选择任何特定的请求或响应类型(例如 |
|
强制会话的存在。因此,这样的论点从来都不是 |
|
当前经过身份验证的用户 — 可能是特定的 |
|
请求的 HTTP 方法。 |
|
当前请求区域设置,由最具体的 |
|
与当前请求关联的时区,由 |
|
用于访问 Servlet API 公开的原始响应正文。 |
|
用于访问错误响应的模型。永远是空的。 |
|
指定在重定向时使用的属性 — (即要附加到查询中 string) 和 flash 属性临时存储,直到重定向后的请求。 请参阅重定向属性和 Flash 属性。 |
|
对于任何 session 属性的访问,与存储在
session 作为类级别 |
|
用于访问请求属性。看 |
返回值
@ExceptionHandler
方法支持以下返回值:
返回值 | 描述 |
---|---|
|
返回值通过 |
|
返回值指定完整响应(包括 HTTP 标头和正文)
通过以下方式进行转换 |
|
要在正文中呈现包含详细信息的 RFC 9457 错误响应, 请参阅错误响应 |
|
要在正文中呈现包含详细信息的 RFC 9457 错误响应, 请参阅错误响应 |
|
要解析的视图名称 |
|
一个 |
|
要添加到隐式模型中且视图名称隐式确定的属性
通过 |
|
要添加到模型中的属性,其视图名称通过
一个 请注意, |
|
要使用的 view 和 model 属性,以及响应状态(可选)。 |
|
具有 如果以上都不是真的,则 |
任何其他返回值 |
如果返回值与上述任何内容都不匹配,并且不是简单类型(由 BeanUtils#isSimpleProperty 确定), 默认情况下,它被视为要添加到模型的 model 属性。如果是简单类型, 它仍然没有解决。 |