SpringBoot全局异常处理机制和配置拦截器方式
作者:勇敢流流
SpringBoot全局异常处理机制和配置拦截器
关于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页面错误,因此打印了两次。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。