0
点赞
收藏
分享

微信扫一扫

23. SpringBoot默认的错误处理机制

z当我们发生错误 ,会映射这样一个页面:

23. SpringBoot默认的错误处理机制_状态码 

如果我通过Postman去访问这个错误,就会返回一段JSON代码:

 23. SpringBoot默认的错误处理机制_spring_02

 

 

 这原因很简单 是因为 浏览器的请求头携带了 text/html 表示用html来处理显示这个错误 23. SpringBoot默认的错误处理机制_html_03

 

客户端的请求是 */* 的,所以这些都是SpringBoot内部的一些定义的:23. SpringBoot默认的错误处理机制_spring_04

 

 

 

 ErrorMvcAutoConfiguration 是SpringBoot 处理默认错误的自动配置,我们看源码解析:

首先它给容器中添加了以下组件:

1、DefaultErrorAttributes: 跟进去发现 里面是一顿获取信息,包括 错误码 status、 时间戳timestamp、异常信息 exception、error:错误提示、message:异常消息,都是共享的,可以直接拿到。

2、BasicErrorController:

23. SpringBoot默认的错误处理机制_状态码_0523. SpringBoot默认的错误处理机制_html_06

@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);
    }

BesicErrprConyroller 主要讲解

里面注释写的很明白,

23. SpringBoot默认的错误处理机制_状态码_0523. SpringBoot默认的错误处理机制_html_06

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;
    }

}

ModelAndView 来源

所以最后查明了他的 ModeandView 是 ErrorViewResolver哪里来的。ErrorViewResolver  就是被下面这个 DefaultErrorViewResolver处理:

 

---------------------------------------------------

那最后那句代码也些很明白了 如果modelandvie 到最后还是 null(什么文件也没匹配上),那么就会直接创建一个 error 的视图,这个视图也就是我们看到的SpringBoot中那个默认图了!

23. SpringBoot默认的错误处理机制_状态码_09

 

 

3、DefaultErrorViewResolver:

因为这里代码太多 我们抽取主要讲解:

 

 23. SpringBoot默认的错误处理机制_html_10

23. SpringBoot默认的错误处理机制_html_11

4、ErrorPageCustomizer:

这个一旦发生错误第一个就进来这,然后我们看下他源码:

23. SpringBoot默认的错误处理机制_状态码_12 首先new 了一个 ErrorPageCustomizer跟进去:

 

 

23. SpringBoot默认的错误处理机制_spring_13  可以看到这个类 就来注册获取路径,跟进去:

23. SpringBoot默认的错误处理机制_html_14  ====》   23. SpringBoot默认的错误处理机制_状态码_15

 

说明这个东西 一旦出现错误页面,那么就会发送请求 /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这个页面。】

 

23. SpringBoot默认的错误处理机制_状态码_16    23. SpringBoot默认的错误处理机制_html_17

 

 

当然 如果你存在模板 你完全可以自己获取DefaultErrorAttributes组件共享的一下信息,状态码什么的。

作者:咸瑜

举报

相关推荐

0 条评论