当前位置: 首页 > article >正文

【SpringMVC源码三千问】DispatcherServlet源码解析

DispatcherServlet#doDispatch() 是 SpringMVC 处理请求分发的方法,只要是 spring mvc 处理的 http 请求,都会经过 DispatcherServlet 的请求分发处理,从而调用相应的 handler method。

DispatcherServlet#doDispatch() 源码分析:

DispatcherServlet.png

可以看到,DispatcherServlet#doDispatch() 的处理大体分了 6 步:
1、获取 request 对应的 HandlerExecutionChain(它包含 handler 和 interceptors)
2、获取 handler 对应的 HandlerAdapter
3、执行 handler 的前置处理: HandlerInterceptor#preHandle()
4、通过 HandlerAdapter#handler() 来执行处理程序
5、执行 handler 的后置处理:HandlerInterceptor#postHandle()
6、对返回值进行处理(包括正常返回 和 异常处理)

处理程序 handler 始终包装在 HandlerExecutionChain 实例中,HandlerExecutionChain 中可以附带一些 HandlerInterceptor
DispatcherServlet 将首先按给定顺序调用每个 HandlerInterceptor#preHandle() 方法,如果所有 preHandle 都返回 true 的话,才会调用处理程序 handler 本身。

所以,如果我们想要找 url 与 handler method 的映射关系的话,就可以从 DispatcherServlet#getHandler() 来入手,打个断点调试。

HandlerExecutionChain 的获取 和 组装

HandlerExecutionChain 是 handler 的执行链,它是由 handler 和 interceptors 组成的。

HandlerExecutionChain 是通过 DispatcherServlet#getHandler() 来获取的:

/**
 * 将所有的 HandlerMapping 按顺序遍历一次,获取 request 对应的 HandlerExecutionChain。
 */
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

可以看到,在获取 HandlerExecutionChain 时,Spring 会将所有的 HandlerMapping 按顺序遍历一次。
而在 Spring 中有许多 HandlerMapping,最常用的当属 RequestMappingHandlerMapping

HandlerExecutionChain 的获取

HandlerExecutionChain 的获取是在 AbstractHandlerMapping#getHandler() 中完成的。
主要分成了两步:
1、获取 request 对应的 handler 程序
2、将 handler 和 相应的 HandlerInterceptors 组装成 HandlerExecutionChain

getHandler.png

AbstractHandlerMapping#getHandler() 中包含了对 cors 的处理,具体是往 HandlerExecutionChain 中添加了 CorsInterceptor。
@see AbstractHandlerMapping#getCorsHandlerExecutionChain()

HandlerExecutionChain 的构造和组装过程

HandlerExecutionChain 的构造组装是在 AbstractHandlerMapping#getHandlerExecutionChain()

/**
 * 为给定的 handler 构建 HandlerExecutionChain(包含 handler 和 HandlerInterceptor)。
 */
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    // 1、根据 handler 构造 HandlerExecutionChain  
    HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
            (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

    // 2、给 HandlerExecutionChain 添加 HandlerInterceptor  
    for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
        if (interceptor instanceof MappedInterceptor) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
            if (mappedInterceptor.matches(request)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        } else {
            chain.addInterceptor(interceptor);
        }
    }
    return chain;
}

DispatcherServlet 中使用的默认策略接口

DispatcherServlet.properties 中指定了 DispatcherServlet.java 中使用的一些策略接口的默认实现:

# spring-webmvc-5.3.9.jar!/org/springframework/web/servlet/DispatcherServlet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

小结

DispatcherServlet#doDispatch() 是 Spring MVC 处理请求分发的方法,它的处理大体分了 6 步:
1、获取 request 对应的 HandlerExecutionChain(它包含 handler 和 interceptors)
2、获取 handler 对应的 HandlerAdapter
3、执行 handler 的前置处理: HandlerInterceptor#preHandle()
4、通过 HandlerAdapter#handler() 来执行处理程序
5、执行 handler 的后置处理:HandlerInterceptor#postHandle()
6、对返回值进行处理(包括正常返回 和 异常处理)

HandlerExecutionChain 是 handler 的执行链,它是由 handler 和 interceptors 组成的。
HandlerExecutionChain 是由 HandlerMapping#getHandler() 返回的。


http://www.kler.cn/a/15208.html

相关文章:

  • 使用Faiss构建音频特征索引并计算余弦相似度
  • C 语言Day 01 学习总结
  • 淘宝 NPM 镜像源
  • H.265流媒体播放器EasyPlayer.js网页直播/点播播放器WebGL: CONTEXT_LOST_WEBGL错误引发的原因
  • ES6进阶知识二
  • Springboot基于GIS的旅游信息管理系统
  • < 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>
  • 用ChatGPT问DotNet的相关问题,发现DotNet工程师的前景还不错
  • JAVA ssm客户信息管理系统idea开发mysql数据库web结构计算机java编程springMVC
  • 前端如何处理后端一次性传来的10w条数据?
  • 中介者设计模式(Mediator Design Pattern)[论点:概念、组成角色、相关图示、示例代码、适用场景]
  • none of
  • ChatGPT- OpenAI 的 模型(Model) 介绍
  • 深度学习入门:多层感知机实现异或门
  • chatGPT推荐2个key免费使用
  • 法发〔2016〕22号《关于办理刑事案件收集提取和审查判断电子数据若干问题的规定》
  • Day32内部类
  • 现代CMake高级教程 - 第 0 章:命令行小技巧
  • UE5实现建筑剖切效果
  • 【ArcGIS】常见问题总结
  • OpenGL入门教程之 摄像机
  • 浅谈Java线程
  • SEO机制算是让我玩明白了
  • 数据结构与算法超级详细版再次更新
  • 压力应变桥信号处理系列隔离放大器 差分输入转换直流变送模块
  • 【Java基础练习题】多线程IO流操作实现文件的复制(举一反三)