美文网首页
SpringMVC ErrorPage粗解

SpringMVC ErrorPage粗解

作者: 丑人林宗己 | 来源:发表于2021-02-10 15:51 被阅读0次

起因

最近观察生产日志发现偶尔会看到一个/error接口的错误异常,但是从异常堆栈信息里没有找到任何关于真实发生错误的接口路径,以至于排查问题时无从下手。

通过Postman复现一下,效果如下:

image.png

带着如下几个问题来拆分ErrorPage的实现方式:

  • 什么场景会触发ErrorPage页面
  • ErrorPage的实现核心组件包括哪些

ErrorController

通过查找,定位到自己代码依赖着一个自实现的common包,其中有个CustomerErrorController,其访问路径为:

${server.error.path:${error.path:/error}}

在配置文件没有配置server.error.path以及error.path时,路径为/error,逻辑上符合复现的场景,通过debug也确实可以证实。

CustomerErrorController网上找最终发现顶级接口就是ErrorController,利用IDEA工具可以快速看到默认实现的类

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController{  ...  }

@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
    return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
            this.errorViewResolvers);
}

ServerProperties中找到ErrorProperties,其中默认配置的path/error,与CustomerErrorController的路径是相同的。

ErrorMvcAutoConfiguration

/// 核心的组件
ErrorPageCustomizer
ErrorPageRegistrarBeanPostProcessor
ErrorPageFilter
TomcatEmbeddedServletContainerFactory
TomcatErrorPage

// 在ErrorPageFilter中找到
private void setErrorAttributes(HttpServletRequest request, int status,
        String message) {
    request.setAttribute(ERROR_STATUS_CODE, status);
    request.setAttribute(ERROR_MESSAGE, message);
    // 获取到uri就可以知道是哪个接口触发了这段跳转至/error接口
    request.setAttribute(ERROR_REQUEST_URI, request.getRequestURI());
}

// 这几个参数在自定义的ErrorController中是可以读取到,
// 但是通过Debug发现并没有运行到ErrorPageFilter,
// 意味着类似的代码可能在另外的地方也有一份

回到前文提到的两个问题。

什么场景会触发ErrorPage?由于没有找到真正核心的代码,参考ErrorPageFilter的代码如下:(想要一探究竟,考虑从DispatchServlet的流程上去找)

private void doFilter(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response);
        try {
            chain.doFilter(request, wrapped);
            if (wrapped.hasErrorToSend()) {
                handleErrorStatus(request, response, wrapped.getStatus(),
                        wrapped.getMessage());
                response.flushBuffer();
            }
            else if (!request.isAsyncStarted() && !response.isCommitted()) {
                response.flushBuffer();
            }
        }
        catch (Throwable ex) {
            Throwable exceptionToHandle = ex;
            if (ex instanceof NestedServletException) {
                exceptionToHandle = ((NestedServletException) ex).getRootCause();
            }
            handleException(request, response, wrapped, exceptionToHandle);
            response.flushBuffer();
        }
    }

ErrorPage包括哪些核心组件?参照ErrorMvcAutoConfiguration

相关文章

  • SpringMVC ErrorPage粗解

    起因 最近观察生产日志发现偶尔会看到一个/error接口的错误异常,但是从异常堆栈信息里没有找到任何关于真实发生错...

  • web项目配置http code返回值页面

    web.xml 中配置errorPage

  • https粗解

    简单地说https=http+(tls)ssl 相比较于http更加安全。Information Security...

  • URL粗解

    一 什么是URL URL, Uniform Resouce Locator , 统一资源定位符。 二 一般结构 ...

  • UITableView粗解

    设置有多少节-->设置每个节有多少cell-->设置每个节的样式节头(节脚)--> 设置数据源(通过循环一个个加载...

  • 粗解缓存

    缓存 一. 概念 1.1 客户端开发者眼中的缓存 1.2 服务器开发者眼中的缓存 二. 特点 2.1 优点 2.2...

  • SDWebImage粗解

    框架GitHub地址SDWebImage 是什么: 一个UIImageView类别添加Web图像和缓存管理Coco...

  • AFNetworking粗解

    框架GitHub地址AFNetworking 构造: NSURLSession AFURLSessionManag...

  • redis 粗解

    Redis基础知识端口:6379默认16个数据库,下标从0开始单线程:redis是单线程+io多路复用而Memch...

  • 递归(粗解)

    递归,要是简单理解它,可以说不难,就是一个递出去,拿回来的过程,拿一个实际生活里面的例子来说: 周末你带着女朋友去...

网友评论

      本文标题:SpringMVC ErrorPage粗解

      本文链接:https://www.haomeiwen.com/subject/ldahxltx.html