【springboot异常处理】

这里写自定义目录标题

1,Java Servlet规范

异常处理

在web.xml中定义Exception和error-code的映射。

复制代码
<!-- 根据状态码配置 -->
<error-page> 
    <error-code>404</error-code>          
    <location>/404.html</location>
</error-page>

<!-- 状态码为0时可以匹配所有的状态码 -->
<error-page> 
    <error-code>0</error-code>          
    <location>/error.html</location>
</error-page>

<!-- 根据异常类型配置 -->
<error-page> 
    <exception-type>java.lang.NullPointerException</exception-type>          
    <location>/error.html</location>
</error-page>
触发异常

HttpServletResponse.setError();

HttpServletResponse.sendError(status,msg);

2,tomcat 异常处理实现

tomcat请求处理流程
  1. 线程模型

  2. 请求处理流程

异常发生时核心处理类

当异常发生时,首先在StandardHostValve 中匹配,匹配的规则是

  1. 先根据Exception去找错误页面
  2. 再根据code去找错误页面

找到对应的页面后,dispatch到相应的页面,返回给前端进行展示。

如果没有匹配到相应的页面,tomcat使用以下两种Value进行异常处理。

ErrorReportValve

用于在界面上展示错误信息,也就是常见的错误提示:

StandardWrapperValve

收集执行Servlet过程中的错误信息,给ErrorReportValve进行展示。

3,springmvc 异常定制以及扩展

请求处理流程
使用@ControllerAdvice & @ExceptionHandler 配置全局异常处理器

用于处理 HandlerMethod(上图中 Handler) 执行过程中抛出的异常

未配置全局异常处理或者没有匹配到异常时的处理流程
  1. springboot在启动时,自动配置机制,使用 ErrorMvcAutoConfiguration 中注册:BasicErrorController

  2. 同时,注册code为0的ErrorPage
    org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.ErrorPageCustomizer#registerErrorPages

    复制代码
     	@Override
     	public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
     		ErrorPage errorPage = new ErrorPage(
     				this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath()));
     		errorPageRegistry.addErrorPages(errorPage);
     	}

by the way:code为0的错误页面映射,tomcat中的处理逻辑如下:

复制代码
//org.apache.catalina.valves.ErrorReportValve

    protected void report(Request request, Response response, Throwable throwable) {

        int statusCode = response.getStatus();

        // Do nothing on a 1xx, 2xx and 3xx status
        // Do nothing if anything has been written already
        // Do nothing if the response hasn't been explicitly marked as in error
        //    and that error has not been reported.
        if (statusCode < 400 || response.getContentWritten() > 0 || !response.setErrorReported()) {
            return;
        }

        // If an error has occurred that prevents further I/O, don't waste time
        // producing an error report that will never be read
        AtomicBoolean result = new AtomicBoolean(false);
        response.getCoyoteResponse().action(ActionCode.IS_IO_ALLOWED, result);
        if (!result.get()) {
            return;
        }

        ErrorPage errorPage = null;
        if (throwable != null) {
            errorPage = errorPageSupport.find(throwable);
        }
        if (errorPage == null) {
            errorPage = errorPageSupport.find(statusCode);
        }
        if (errorPage == null) {
            // Default error page
            errorPage = errorPageSupport.find(0);
        }
	... //忽略部分代码
	}
  1. 经过code为0的映射处理后,tomcat container组件会把请求dispatch到"/error"页面,最终找到BasicErrorController 处理器:
    BasicErrorController 处理器的处理逻辑如下:
    BasicErrorController 通过 Accept 头判断需要生成哪种 MediaType 的响应
    3.1 如果要的不是 text/html,走 MessageConverter 流程
    3.2 如果需要 text/html,走 mvc 流程,此时又分两种情况
    a. 配置了 ErrorViewResolver,根据状态码去找 View
    b. 没配置或没找到,用 BeanNameViewResolver 根据一个固定为 error 的名字找到 View,即所谓的 WhitelabelErrorView
以上处理过程中的未捕获异常,交给tomcat去处理异常

返回给tomcat的ErrorReportValve去处理,展示异常如前图所示。

相关推荐
懒鸟一枚11 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我1234513 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑13 小时前
Sentinel安装
java·后端·微服务
IT_陈寒13 小时前
SpringBoot自动配置失灵?你可能忘了这个关键注解
前端·人工智能·后端
碎碎念_49213 小时前
SpringBoot + Vue 前后端分离从 0 到 1 完整环境配置流程
vue.js·spring boot·后端
逝水无殇13 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
YIAN14 小时前
从手写 Agent 工具到 MCP 协议:一文搞懂大模型跨进程跨语言工具调用
后端·agent·mcp
小兔崽子去哪了14 小时前
Docker 删除镜像后磁盘空间没有释放?
后端·docker·容器
凤凰院凶涛QAQ15 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
高明珠15 小时前
麒麟 V10 SP1 排查实录:ttyS5 每 10 秒莫名收到一批报文,元凶是 eGTouchD
后端