ErrorMvcAutoConfiguration
1.DefaultErrorAtrributes:
帮助我们在页面共享信息。2.BasicErrorController:
//默认处理 /error 请求 @Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController {...}两种请求的处理
//产生html类型的数据,浏览器产生的错误来到这里处理 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); //去哪个页面作为错误页面? ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); } //产生json类型的数据,其它客户端的错误来到这里进行处理 @RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity<>(status); } Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); return new ResponseEntity<>(body, status); }resolveErrorView
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); if (modelAndView != null) { return modelAndView; } } return null; }DefaultErrorViewResolver 内部代码 DefaultErrorViewResolver 内部函数
@Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView modelAndView = resolve(String.valueOf(status.value()), model); if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) { modelAndView = resolve(SERIES_VIEWS.get(status.series()), model); } return modelAndView; } private ModelAndView resolve(String viewName, Map<String, Object> model) { //默认去找一个error/错误码的页面,类似 error/404 String errorViewName = "error/" + viewName; //如果模板引擎可以解析这个页面地址,就使用引擎解析 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext); //如果引擎可用的情况下,就创建并返回一个新的视图 if (provider != null) { return new ModelAndView(errorViewName, model); } //如果无法被引擎解析则去resourceProperties寻找静态资源 return resolveResource(errorViewName, model); } private ModelAndView resolveResource(String viewName, Map<String, Object> model) { //在静态资源文件找errorViewName对应的页面, 比如 error/404.html for (String location : this.resourceProperties.getStaticLocations()) { try { Resource resource = this.applicationContext.getResource(location); resource = resource.createRelative(viewName + ".html"); if (resource.exists()) { return new ModelAndView(new HtmlResourceView(resource), model); } } catch (Exception ex) { } } return null; }3.ErrorPageCustomizer:
@Value("${error.path:/error}") private String path = "/error"; 一旦系统出现4xx或者5xx之类的错误,ErrorPageCustomizer就会生效(定制错误的响应规则) 来到/error请求,4.DefaultErrorViewResolver:
通过DefaultErrorAttributes的源码可以知道,错误页面能够获得信息:
timestamp: 时间戳 status: 状态码 error: 错误提示 exception: 异常对象 message: 异常信息 errors: jsr303数据校验相关错误如果模板引擎找不到对应的资源,比如将错误页面放到静态资源文件件下
此时,无法动态获得错误信息
模板引擎的templates文件夹和 静态资源 文件夹下都没有
此时,来到SpringBoot的默认错误提示页面