自定义静态错误页面
若 Sprng Boot 项目没有使用模板引擎,当程序发生异常时,Spring Boot 的默认错误视图解析器(DefaultErrorViewResolver)则会解析静态资源文件夹下 error 目录中的静态错误页面。
精确匹配
我们可以根据错误状态码(例如 404、500、400 等等)的不同,分别创建不同的静态错误页面(例如 404.html、500.html、400.html 等等),并将它们存放在静态资源文件夹下的 error 目录中。当发生异常时,Spring Boot 会根据错误状态码精确匹配到对应的错误页面上。
错误页面优先级
定制 Spring Boot 错误页面所有方式优先级顺序为:自定义动态错误页面(精确匹配)>自定义静态错误页面(精确匹配)>自定义动态错误页面(模糊匹配)>自定义静态错误页面(模糊匹配)>自定义 error.html。
定制错误数据
我们知道,Spring Boot 提供了一套默认的异常处理机制,其主要流程如下:
- 发生异常时,将请求转发到“/error”,交由 BasicErrorController(Spring Boot 默认的 Error 控制器) 进行处理;
- BasicErrorController 根据客户端的不同,自动适配返回的响应形式,浏览器客户端返回错误页面,机器客户端返回 JSON 数据。
- BasicErrorController 处理异常时,会调用 DefaultErrorAttributes(默认的错误属性处理工具) 的 getErrorAttributes() 方法获取错误数据。
我们还可以定制 Spring Boot 的错误数据,具体步骤如下。
- 自定义异常处理类,将请求转发到 “/error”,交由 Spring Boot 底层(BasicErrorController)进行处理,自动适配浏览器客户端和机器客户端。
- 通过继承 DefaultErrorAttributes 来定义一个错误属性处理工具,并在原来的基础上添加自定义的错误数据。
1. 自定义异常处理类
被 @ControllerAdvice 注解的类可以用来实现全局异常处理,这是 Spring MVC 中提供的功能,在 Spring Boot 中可以直接使用。
1)创建一个名为 UserNotExistException 的异常类,代码如下。
/**
* 自定义异常
*/
public class UserNotExistException extends RuntimeException {
public UserNotExistException() {
super("用户不存在!");
}
}
2)在 IndexController 添加以下方法,触发 UserNotExistException 异常,代码如下。
@Controller
public class IndexController {
......
@GetMapping(value = {"/testException"})
public String testException(String user) {
if ("user".equals(user)) {
throw new UserNotExistException();
}
//跳转到登录页 login.html
return "login";
}
}
3)在 net.biancheng.www.controller 中,创建一个名为 MyExceptionHandler 异常处理类,代码如下。
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
//向 request 对象传入错误状态码
request.setAttribute("javax.servlet.error.status_code",500);
//根据当前处理的异常,自定义的错误数据
map.put("code", "user.notexist");
map.put("message", e.getMessage());
//将自定的错误数据传入 request 域中
request.setAttribute("ext",map);
return "forward:/error";
}
}
2. 自定义错误属性处理工具
1)创建一个错误属性处理工具类 MyErrorAttributes(继承 DefaultErrorAttributes ),通过该类我们便可以添加自定义的错误数据,代码如下。
//向容器中添加自定义的储物属性处理工具
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, options);
//添加自定义的错误数据
errorAttributes.put("company", "www.biancheng.net");
//获取 MyExceptionHandler 传入 request 域中的错误数据
Map ext = (Map) webRequest.getAttribute("ext", 0);
errorAttributes.put("ext", ext);
return errorAttributes;
}
}
2)在 templates/error 目录下,创建动态错误页面 5xx.html,代码如下。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>自定义 error.html</title>
</head>
<body>
<p>status:<span th:text="${status}"></span></p>
<p>error:<span th:text="${error}"></span></p>
<p>timestamp:<span th:text="${timestamp}"></span></p>
<p>message:<span th:text="${message}"></span></p>
<p>path:<span th:text="${path}"></span></p>
<!--取出定制的错误信息-->
<h3>以下为定制错误数据:</h3>
<p>company:<span th:text="${company}"></span></p>
<p>code:<span th:text="${ext.code}"></span></p>
<p>path:<span th:text="${ext.message}"></span></p>
</body>
</html>
3)启动 Spring Boot,访问“http://localhost:8080/testException?user=user”,结果如下图。