• 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);
        }
    BesicErrprConyroller 主要讲解

    里面注释写的很明白,

        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中那个默认图了!

    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

  • 相关阅读:
    【Rollo的Python之路】Python 编码与解码
    【Rollo的Python之路】Python 队列 学习笔记 queue
    【Rollo的Python之路】Python 同步条件 学习笔记 Event
    【Rollo的Python之路】Python 条件变量同步 学习笔记 Condition
    【Rollo的Python之路】Python 信号量 学习笔记 Semaphore
    十天冲刺-09
    十天冲刺-08
    十天冲刺-07
    十天冲刺-06
    十天冲刺-05
  • 原文地址:https://www.cnblogs.com/bi-hu/p/15139597.html
Copyright © 2020-2023  润新知