【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去处理,展示异常如前图所示。

相关推荐
ServBay5 分钟前
DeepSeek 又出王炸,用 DeepInfer 搭建自己的服务是不是很容易?
后端·ai编程·deepseek
譕痕14 分钟前
stripe 实例
java·开发语言·stripe·checksession
墨子夕23 分钟前
设计模式——Java × Python 双语言精讲 · 23 个经典模式 + 现代演进(前言篇)
java·开发语言·设计模式
骇客野人28 分钟前
Linux 全套实操方案(含目录详解、文件传输、日志、文件规范、环境变量、Java 应用部署运维)
java·linux·运维
.Bryce.1 小时前
MCP+A2A+ANP,Agent通信协议的完整知识地图
java·人工智能·后端·agent·通信协议
JuiceFS1 小时前
面向 EB 级 AI 存储:JuiceFS 企业版架构演进
人工智能·后端
SL_staff1 小时前
规则引擎选型陷阱:为什么QPS不是JVS-Rules对比Drools的核心指标
java·开源·全栈
LMT流氓兔1 小时前
第五单元——第4课:给工具参数加校验
java·前端·算法·ai·langchain
eleven_4u1 小时前
RocketMQ相关问题
java·运维·中间件
迷途小羔羊1 小时前
项目概述
java·javascript·后端