SpringBoot - Web异常处理
了解SpringBoot进行Web开发时的异常处理机制。
1. 异常处理机制
1.1 默认异常处理
默认情况下,SpringBoot提供/error
映射处理所有的异常,
并在Servlet容器中注册为全局错误处理页面。
对于浏览器客户端,SpringBoot响应一个"Whitelabel"错误视图,
以HTML格式展示,其中包含错误,HTTP状态码和异常的详细信息,看起来像这样:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Jun 05 15:19:37 CST 2021
There was an unexpected error (type=Internal Server Error, status=500).
/ by zero
对于应用程序客户端,SpringBoot则响应JSON视图,其中包含的信息和HTML视图的信息相同,
看起来像这样:
{
"timestamp": "2021-06-05T07:19:31.987+00:00",
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.ArithmeticException",
"message": "/ by zero",
"path": "/test"
}
1.2 自定义错误页面
我们可以编写自定义错误页面,使用SpringBoot的默认处理机制来自定义展示错误信息。
在默认静态资源文件目录下(/public
,/static
,/resources
,/META-INF/resources
)创建/error
目录,
放入静态HTML页面,会被SpringBoot自动解析并使用。错误页面命名为4xx或5xx(5xx处理所有HTTP状态以5开头的错误类型,
500只处理HTTP状态码为500的错误类型),SpringBoot会自动根据HTTP状态码选择对应的错误页面。
也可以使用模板引擎对SpringBoot产生的错误信息处理并展示,在模板目录(/templates
)下创建/error
目录,
放入模板文件,也会被SpringBoot自动解析并使用。
举个例子(使用Thymeleaf):
<!-- src/main/resources/templates/error/5xx.html -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>您访问的页面出现错误</title>
</head>
<body>
<h1>服务器内部错误</h1>
HTTP状态:<span th:text="${#request.getAttribute('status')}"></span><br>
时间戳:<span th:text="${#request.getAttribute('timestamp')}"></span><br>
错误信息:<span th:text="${#request.getAttribute('error')}"></span><br>
异常类型:<span th:text="${#request.getAttribute('exception')}"></span><br>
异常信息:<span th:text="${#request.getAttribute('message')}"></span><br>
请求路径:<span th:text="${#request.getAttribute('path')}"></span><br>
绑定错误:<span th:text="${#request.getAttribute('errors')}"></span><br>
堆栈信息:<span th:text="${#request.getAttribute('trace')}"></span>
</body>
</html>
SpringBoot提供了8个参数封装了由默认异常处理机制(/error
)产生的数据:
参数名 | 信息 | 配置节点 | 备注 |
---|---|---|---|
status |
HTTP状态码 | - | 永远开启 |
timestamp |
时间戳 | - | 永远开启 |
error |
错误信息 | - | 永远开启 |
exception |
异常类型 | server.error.include-exception |
默认关闭,需要手动开启 |
message |
异常信息 | server.error.include-message |
默认关闭,需要手动开启 |
path |
请求路径 | - | 永远开启 |
trace |
堆栈信息 | server.error.include-stacktrace |
默认关闭,需要手动开启 |
errors |
绑定错误信息 | server.error.include-binding-errors |
默认关闭,需要手动开启 |
Thymeleaf模板可以使用${#request.getAttribute()}
的方式获取以上参数。
1.3 自定义错误处理机制
我们可以自定义错误处理机制来替换默认行为。
1.3.1 @ControllerAdvice + @ExceptionHandler
被@ControllerAdvice
注解的类被称为Controller增强器,可以实现以下三个功能:
- 全局异常处理:类中被@ExceptionHandler注解的方法可以处理全部Controller产生的异常;
- 全局数据绑定:类中被@InitBinder注解的方法可以进行全局数据绑定;
- 全局数据预处理:类中被@ModelAttribute注解的方法可以将返回值放入model,供其他Controller使用。
注解@ExceptionHandler
可以使被注解的方法被Spring用来处理异常。被此注解标记的方法被称为异常处理器。
它有一个属性:
- Class<? extends Throwable>[] value:能够处理的异常类型,可以处理多个异常。
举个例子:
@ControllerAdvice
public class GlobalExceptionHandler {
// 被@ExceptionHandler注解的方法为异常处理器
// 在Controller增强器中的异常处理器可以处理全局异常
// 在某个Controller中的异常处理器只能处理当前Controller中方法出现的异常
@ExceptionHandler(ArithmeticException.class)
public String handleArithmeticException(Exception e, Model model) {
model.addAttribute("exception", e);
return "error/500";