关于SpringBoot的全局异常处理,其实十分简单。首先,要新建一个SpringBoot项目添加两个依赖,spring-boot-starter-web和spring-boot-starter-thymeleaf。
这个时候,我们便可以把异常信息展示在thymeleaf页面。
编写接口:
以往的SpringMVC配置在SpringBoot项目中依然生效。所以可以通过实现HandlerExceptionResolver接口或者添加@ExceptionHandler注解来处理全局异常。
@ControllerAdvice
public class GlobalExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView("01");
mv.addObject("error",ex.getMessage());
return mv;
}
}
@ControllerAdvice
public class GlobalExceptionHandler2 {
@ExceptionHandler(ArithmeticException.class)
public ModelAndView resolveException( Exception ex) {
ModelAndView mv = new ModelAndView("01");
mv.addObject("error",ex.getMessage());
return mv;
}
}
thymeleaf视图必须放在/resources/templates文件夹下,此时需要新建一个01.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试页面</title>
</head>
<body>
<h4>异常信息显示:</h4>
<div th:text="${error}"></div>
</body>
</html>
注意:SpringBoot项目里面freemarker页面和thymeleaf页面不需要配置视图解析器,Spring会自动帮我们识别并渲染ftlh和html页面。
测试:
以上是SpringMVC配置在SpringBoot中依然适用。
但是基于SpringBoot项目的异常配置,SpringBoot自己也有一套全局异常处理机制。
SpringBoot异常处理
默认方案,在静态页面里面展示异常信息:
但是,必须要在静态资源文件夹下新建error文件夹,里面放自己的错误页面信息,4xx和5xx为模糊查询,SpringBoot支持4xx和5xx的状态错误。
这里为了省事,我就在页面里放了一个div输出一句话。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4xx</title>
</head>
<body>
<div>4xx-static-html</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5xx</title>
</head>
<body>
<div>5xx-static-html</div>
</body>
</html>
测试结果为页面显示5xx-static-html,在这里还有一个小细节,假如我们定义了一个精确的状态码页面,例如数学算术错误为500,定义了一个500.html,那么是优先显示500的页面还是5xx的页面呢,这就涉及一个优先级的问题。在这里先埋下一个伏笔,继续往下走。
我们知道thymeleaf实际上是一个动态页面,所以同样的,我们在templates文件下新建error文件夹放两个html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4xx</title>
</head>
<body>
<div>这是动态展示错误的页面:</div>
<table border="1">
<tr>
<td>出错路径</td>
<td th:text="${path}"></td>
</tr>
<tr>
<td>出错时间</td>
<td th:text="${timestamp}"></td>
</tr>
<tr>
<td>错误信息</td>
<td th:text="${error}"></td>
</tr>
<tr>
<td>状态</td>
<td th:text="${status}"></td>
</tr>
</table>
</body>
</html>
当我们在url地址请求一个不存在的页面时触发,
测试:
好了,到这里要开始进入正题。
由于我们的错误是数学算术错误,返回的是java.lang.ArithmeticException,这样显然是很难交代的。首先SpringBoot为我们额外提供了三个异常信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>5xx</title>
</head>
<body>
<div>这是动态展示错误的页面:</div>
<table border="1">
<tr>
<td>出错路径</td>
<td th:text="${path}"></td>
</tr>
<tr>
<td>出错时间</td>
<td th:text="${timestamp}"></td>
</tr>
<tr>
<td>错误信息</td>
<td th:text="${error}"></td>
</tr>
<tr>
<td>状态</td>
<td th:text="${status}"></td>
</tr>
<tr>
<td>异常</td>
<td th:text="${exception}"></td>
</tr>
<tr>
<td>堆栈</td>
<td th:text="${trace}"></td>
</tr>
<tr>
<td>异常信息</td>
<td th:text="${message}"></td>
</tr>
</table>
</body>
</html>
exception、trace和message。
假如我们配置完5xx.html便急着去测试,结果如下:
这三个东西结果为空,那么小伙伴们肯定很想知道这三个东西究竟显示的是什么玩意儿。别急,我们可以在application.properties中配置三个东西。
server.error.include-exception=true
server.error.include-message=always
server.error.include-stacktrace=always
这三个是什么东西呢,想深究的同学可以回去看看底层。从字面意思理解,便是开启这三个东西,默认为不展示。
测试:
原本是测试显示的是java.lang.ArithmeticException,在这里只需要进行全局异常处理即可。
/**
* 将该类注册到 Spring 容器中,此时,默认的 DefaultErrorAttributes 就会失效
*/
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
//这是默认的异常数据
Map<String, Object> map = super.getErrorAttributes(webRequest,options);
//获取异常
String exception = (String) map.get("exception");
if ("java.lang.ArithmeticException".equals(exception)){
map.put("exception","数学算术异常");
}
return map;
}
}
SpringBoot配置拦截器
SpringBoot的拦截器配置也是十分简单,只需要把往Spring注册一个拦截器即可。
为了方便演示,小编自定义一个拦截器,在控制台打印了三句话。
随后新建一个config包把该类注册到Spring容器中。
大功告成,进入测试环节:
这里打印了两次的原因是,第一次拦截的是happy请求,第二次拦截的是404页面错误,因此打印了两次。