1.默认的处理流程
Spring boot提供了默认的异常处理方式,当出现异常时就会默认映射到 error目录(static下面或者templates/error)
错误页面的查找优先级:假如为404错误: 404页面 => 4XX页面 => error页面
为了对用户能友好的展示,可以在error目录下新增404.html,500.html和error.html等文件
2.设置全局异常处理
通过注解@ControllerAdvice来实现统一的异常拦截处理
定义在handler包中
@ControllerAdvice // 拦截控制器的异常
public class ControllerExceptionHandler {
// 获取日志对象,写入异常信息
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(Exception.class) // 标识这个方法可以做异常处理
public ModelAndView exceptionHandler(HttpServletRequest request, Exception e) throws Exception{
logger.error("Request URL : {}, Exception : {}", request.getRequestURL(),e.getMessage());
// 判断该异常是否已经自定义过,未定义过则为null,已定义则抛出异常,交由自定义的异常处理类解决
if (AnnotationUtils.findAnnotation(e.getClass(),ResponseStatus.class) != null) {
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url", request.getRequestURL());
mv.addObject("exception",e);
mv.setViewName("error/error");
return mv;
}
}
3.定义异常显示页面:/resources/templates/error/error.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>错误</title>
</head>
<body>
<h1>错误</h1>
<div>
<!-- remove=tag会拿掉html标签,再配合html的注释语法,这样页面上就不会显示异常信息了,而是显示在页面源码中 -->
<div th:utext="'<!--'" th:remove="tag"></div>
<div th:utext="'Failed Request URL : ' + ${url}" th:remove="tag"></div>
<div th:utext="'Exception message : ' + ${exception.message}" th:remove="tag"></div>
<ul th:remove="tag">
<!-- 遍历exception对象中的错误信息 -->
<li th:each="st : ${exception.stackTrace}" th:remove="tag"><span th:utext="${st}" th:remove="tag"></span></li>
</ul>
<div th:utext="'-->'" th:remove="tag"></div>
</div>
</body>
</html>
4.定义404异常处理
上面定义的拦截器会拦截所有异常,但类似404的异常,我们希望能返回特定的页面
通过@ResponseStatus注解加载自定义异常类,然后在拦截器中判断异常是否已经自定义过,若已定义则抛出异常,交由自定义的异常处理类解决
@ResponseStatus(HttpStatus.NOT_FOUND) // 加载自定义异常类,参数为异常类型
public class NotFoundException extends RuntimeException{
public NotFoundException() {
}
public NotFoundException(String message) {
super(message);
}
public NotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
5.项目结构
参考:https://www.bilibili.com/video/av62555970