23. SpringBoot默认的错误处理机制
z当我们发生错误 ,会映射这样一个页面:
如果我通过Postman去访问这个错误,就会返回一段JSON代码:
这原因很简单 是因为 浏览器的请求头携带了 text/html 表示用html来处理显示这个错误
客户端的请求是 */* 的,所以这些都是SpringBoot内部的一些定义的:
ErrorMvcAutoConfiguration 是SpringBoot 处理默认错误的自动配置,我们看源码解析:
首先它给容器中添加了以下组件:
1、DefaultErrorAttributes: 跟进去发现 里面是一顿获取信息,包括 错误码 status、 时间戳timestamp、异常信息 exception、error:错误提示、message:异常消息,都是共享的,可以直接拿到。
2、BasicErrorController:

@Controller //这里说明去映射 取值‘server.error.path’,如果取值失败就去取error.path值,如果也没取到 就用/error @RequestMapping({"${server.error.path:${error.path:/error}}"}) public class BasicErrorController extends AbstractErrorController { private final ErrorProperties errorProperties; //-----------------下面2组件 上面是 类头-------------------------- @RequestMapping( produces = {"text/html"} //所以这里是浏览器解析时 执行这个方法 ) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = this.getStatus(request);//获取状态码 Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); //设置状态码 ModelAndView modelAndView = this.resolveErrorView(request, response, status, model); //这里说明 那个页面作为错误页面 ;包含页面地址和内容 跟进去可以发现modelAndView是怎么获取的! return modelAndView == null ? new ModelAndView("error", model) : modelAndView; } @RequestMapping //没任何限制 所以这里是除了浏览器(text/html)解析时执行 这里主要是JSON @ResponseBody public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = this.getStatus(request); return new ResponseEntity(body, status); }
里面注释写的很明白,

protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) { for (ErrorViewResolver resolver : this.errorViewResolvers) { ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); //可以发现这里的ModeAndView是从ErrorViewResolver来的 if (modelAndView != null) { //如果获取的ModeAndView不是null 就返回 不然然后null return modelAndView; } } return null; } }
所以最后查明了他的 ModeandView 是 ErrorViewResolver哪里来的。ErrorViewResolver 就是被下面这个 DefaultErrorViewResolver处理:
---------------------------------------------------
那最后那句代码也些很明白了 如果modelandvie 到最后还是 null(什么文件也没匹配上),那么就会直接创建一个 error 的视图,这个视图也就是我们看到的SpringBoot中那个默认图了!
3、DefaultErrorViewResolver:
因为这里代码太多 我们抽取主要讲解:
4、ErrorPageCustomizer:
这个一旦发生错误第一个就进来这,然后我们看下他源码:
首先new 了一个 ErrorPageCustomizer跟进去:
可以看到这个类 就来注册获取路径,跟进去:
====》
说明这个东西 一旦出现错误页面,那么就会发送请求 /error ,等待别处理。
以上几个顺序捋捋 并 总结:(逻辑区)
1.首先一旦发生错误 会 ErrorPageCustomizer 发送/error请求,
2.然后 BasicErrorController 来处理这个 错误请求啊 ,我们看源码也知道,然后看请求头 然后调用哪个方法(返回JSNO 还是 HTML代码),然后如果是HTML/html(浏览器),那么就去创建modelandview,创建方法是用 resolveErrorView 这个方法 【后面执行第三步】,如果最后的最后【第三步之后】,ModeAndView 还是 null 。那就用 error 的驶视图(ErrorMvcAutoConfiguration 最上面有定义) 这个视图也就是我们看到的SpringBoot那个默认视图了。
3. resolveErrorView 这个方法 然后进去然后就匹配 ,如果有模板框架 且 template文件夹下存在 error/状态码.html 就会直接匹配、如果不存在也会在静态文件夹中 匹配 error/状态码.html ,如果匹配到了 也是直接用即可,,,,如果最后的最后 模板文件夹 和 所有静态文件夹下 匹配不到 error/状态码.html ,最终返回 NULL,那就是 回到第二步 ,直接用 error 视图,跟进去发现是SpringBoot 定义的那个默认视图。
好了 那么DefaultErrorAttributes这个组件主要是开放了很多信息,用模板可以直接获取的,,,,,,${xxxx}
那么如何定制错误的页面:
1: 有模板框架 就直接放在template文件夹下面,, 因为视图名是 error/状态码.html 所以创建一个error 文件夹 下面放即可。
2:没有模板就放在静态资源文件夹下,后面操作和1一样。
注意,4xx 和 5xx 也是匹配的 ,4xx包含4开头的所有错误,5那就是5开头的所有错误,,,,
匹配原则:精准第一,模糊第二【意思如果存在404 和 4xx页面,那么如果发生404错误 使用的是404.html 如果不存在404.html 那就使用4xx这个页面。】
当然 如果你存在模板 你完全可以自己获取DefaultErrorAttributes组件共享的一下信息,状态码什么的。
本文来自博客园,作者:咸瑜,转载请注明原文链接:https://www.cnblogs.com/bi-hu/p/15139597.html