spring mvc DispatcherServlet解读

DispatcherServlet的继承和实现

IDEA按快捷键:ctrl+alt+u,就可以查看DispatcherServlet的继承的类和实现的接口。

从继承图可以得知:

  • DispatcherServlet本质是一个HttpServlet
  • HttpServletBean,FrameworkServlet,DispatcherServlet是属于SpringMVC的类

DispatcherServlet初始化

DispatcherServlet

DispatcherServlet看initStrategies(),该方法用于初始化各类解析器。

onRefresh(ApplicationContext context),该方法用于刷新策略

/*** This implementation calls {@link #initStrategies}.
*/
//刷新策略
@Override
protected void onRefresh(ApplicationContext context) {initStrategies(context);
}/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
//初始化各类解析器
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);    //初始化分段上传解析器initLocaleResolver(context);     //初始化地域解析器initThemeResolver(context);           //初始化主题解析器initHandlerMappings(context);     //初始化处理器映射initHandlerAdapters(context);     //初始化处理器适配器initHandlerExceptionResolvers(context);       //初始化处理器异常解析器initRequestToViewNameTranslator(context);     //初始化请求到视图名解析器initViewResolvers(context);        //初始化视图解析器initFlashMapManager(context);      //初始化快闪映射
}

FrameworkServlet

onRefresh(ApplicationContext context)重写于父类FrameworkServlet,点开FrameworkServlet,我们主要看看它initServletBean()方法,FrameworkServlet的onRefresh(ApplicationContext context)是个空实现,因为在DispatcherServlet实现了。

initServletBean()是重写HttpServletBean的initServletBean(),先看看initServletBean()干了什么:

  • 调用了initWebApplicationContext(),初始化了WebApplicationContext,而WebApplicationContext是继承于ApplicationContext接口的,所以我们知道了initWebApplicationContext是初始化了一个上下文。
  • 调用了initFrameworkServlet(),点开发现是个空实现。
@Overrideprotected final void initServletBean() throws ServletException {//*******查看核心部分**********try {//这里初始化WebApplicationContextthis.webApplicationContext = initWebApplicationContext();initFrameworkServlet();   //空实现,给其他继承类实现}catch (ServletException | RuntimeException ex) {logger.error("Context initialization failed", ex);throw ex;}//*******其他日志的不看********}

点开initWebApplicationContext(),因为太长了,所以放图片。

上半段:

  • 通过servlet上下文中创建了一个rootcontext
  • 中间的if代码块在上下文刷新时才会运行,初始化状态时,webapplicationcontext是null,所以初始化时是不进入的。该段代码主要用于刷新上下文

下半段:

  • 查找已经存在的注册的上下文,如果没有就用rootContex去创建一样上下文。
  • refreshEventReceived默认是false
/** Flag used to detect whether onRefresh has already been called. */
private volatile boolean refreshEventReceived = false;
  • onRefresh()方法被重写了,所以我们知道在Dispatchservlet中,会初始化各种解析器(如:视图解析器等)

HttpServletBean

假设WEB-INF 目录下查找配置文件信息如下:

<!-- 部署 DispatcherServlet -->
<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!-- 表示容器再启动时立即加载servlet --><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

HttpServletBean是抽象类,ctrl+F12查看方法。

找到init()方法,这个是我们要找到的重要方法

  • init()方法是重写了GenericServlet的init()方法,所以这个是最根本的初始化方法。

让我们看看init()干了什么:

ServletConfigPropertyValues是用来加载Servlet配置,ServletConfigPropertyValues是HttpServletBean的内部静态类,它负责取到web.xml中init-param(如:contextConfigLocation)

@Overridepublic final void init() throws ServletException {//加载web.xml中init-param(如:contextConfigLocation)// Set bean properties from init parameters.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {//BeanWrapper将HttpServletBean进行包装BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//ServletContext的资源加载器ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());//注册资源编辑器bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));//为HttpServletBean初始化包装,默认实现是空的initBeanWrapper(bw);//给包装类传递web.xml中init-parambw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}// Let subclasses do whatever initialization they like.//initServletBean()是交给子类实现的,FrameworkServlet实现了这个方法initServletBean();}

初始化总结

各类的初始化工作:

  • HttpServletBean 主要初始化web.xml资源
  • FrameworkServlet 获取servlet上下文创建WebApplicationContext
  • DispatcherServlet 初始化各类解析器

调用过程

  1. HttpServletBean ---- init()
  2. FrameworkServlet ---- initServletBean()
  3. FrameworkServlet ---- initWebApplicationContext()
  4. DispatcherServlet ---- onRefresh(ApplicationContext context)
  5. DispatcherServlet ---- initStrategies(ApplicationContext context)
  6. DispatcherServlet ---- initXXX(ApplicationContext context)各种解析器组件的初始化

DispatcherServlet处理请求

核心成员变量

DispatcherServlet的核心成员变量就是上面DispatcherServlet初始化中initStrategies(ApplicationContext context)初始化的各类处理器。

/** MultipartResolver used by this servlet. */@Nullableprivate MultipartResolver multipartResolver;/** LocaleResolver used by this servlet. */@Nullableprivate LocaleResolver localeResolver;/** ThemeResolver used by this servlet. */@Nullableprivate ThemeResolver themeResolver;/** List of HandlerMappings used by this servlet. */@Nullableprivate List<HandlerMapping> handlerMappings;/** List of HandlerAdapters used by this servlet. */@Nullableprivate List<HandlerAdapter> handlerAdapters;/** List of HandlerExceptionResolvers used by this servlet. */@Nullableprivate List<HandlerExceptionResolver> handlerExceptionResolvers;/** RequestToViewNameTranslator used by this servlet. */@Nullableprivate RequestToViewNameTranslator viewNameTranslator;/** FlashMapManager used by this servlet. */@Nullableprivate FlashMapManager flashMapManager;/** List of ViewResolvers used by this servlet. */@Nullableprivate List<ViewResolver> viewResolvers;

doService()

在浏览器输入位置时,会触发DispatcherServletdoService(HttpServletRequest request, HttpServletResponse response)去处理请求。

doService(HttpServletRequest request, HttpServletResponse response)又会去调用doDispatch(HttpServletRequest request, HttpServletResponse response)去处理请求

doDispatch()

doDispatch比较多代码分成两段截图

上半段代码

下半段代码


还有

getHandler()

getHandler()会遍历所有的handlerMapping,并找出匹配的handler。

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;}

关于handlerMapping接口的实现类

handlerMapping接口的实现类有许多,RequestMappingHandlerMapping,该类用于创建@RequestMapping和@Controller注解的实例

spring mvc DispatcherServlet解读相关推荐

  1. Spring MVC DispatcherServlet改造为 CSE RestServlet 常见问题汇编

    [摘要] 本文是使用CSE RestServlet替换Spring MVC DispatcherServlet常见问题汇总. 将Spring Boot的REST应用改造为CSE的REST应用的核心部分 ...

  2. spring mvc DispatcherServlet详解之三---request通过ModelAndView中获取View实例的过程

    整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet第二步:通过request从Controller获取ModelAndView.现在来讲解第三步:reques ...

  3. spring mvc DispatcherServlet详解之前传---FrameworkServlet

    做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...

  4. spring mvc DispatcherServlet详解之二---request通过Controller获取ModelAndView过程

    整个spring mvc的架构如下图所示: 上篇文件讲解了DispatcherServlet通过request获取控制器Controller的过程,现在来讲解DispatcherServletDisp ...

  5. spring mvc DispatcherServlet详解之一--request通过HandlerMaping获取控制器Controller过程

    整个spring mvc的架构如下图所示: 现在来讲解DispatcherServletDispatcherServlet的第一步:获取控制器. HandlerMapping HandlerMappi ...

  6. spring mvc DispatcherServlet详解之四---视图渲染过程

    整个spring mvc的架构如下图所示: 现在来讲解DispatcherServletDispatcherServlet的最后一步:视图渲染.视图渲染的过程是在获取到ModelAndView后的过程 ...

  7. spring mvc DispatcherServlet详解之interceptor和filter的区别

    首先我们看一下spring mvc Interceptor的功能及实现: http://wenku.baidu.com/link?url=Mw3GaUhCRMhUFjU8iIDhObQpDcbmmRy ...

  8. spring mvc DispatcherServlet详解之一---处理请求深入解析

    要深入理解spring mvc的工作流程,就需要先了解spring mvc的架构: 从上图可以看到 前端控制器DispatcherServlet在其中起着主导作用,理解了DispatcherServl ...

  9. spring mvc DispatcherServlet详解之前传---前端控制器架构

    前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端.前端控制器既可以使用Filter实现 ...

最新文章

  1. RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列
  2. bat常用命令操作符列表
  3. [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.15
  4. leetcode 542. 01 Matrix | 542. 01 矩阵(图解,广度优先搜索)
  5. qpython3可以调用哪些库_Python3 如何使用asyncio库在调用第三方模块(存在IO等待)的情况下实现协程?...
  6. oracle 邮件过程,oracle 发邮件 存储过程
  7. 今天的出了校门的即时通讯
  8. 刑事科学技术专业与计算机专业,辽宁警察学院刑事科学技术专业
  9. 读写序列(pickle)
  10. 我的世界服务器领地怎么无限大,我的世界:Minecraft都市传说,MC无限大?让我们一起寻找边界吧...
  11. 数据分析常用名词解释
  12. 这座研究所出了8位菲尔兹奖得主: 教授没有发论文压力,不指定方向,不必教课...
  13. 2020年最全最好用的在线文档盘点,建议收藏
  14. 【博客园-问题反馈】使用谷歌浏览器 百度图床图片无法显示
  15. IGP LDP同步技术剖析
  16. CPU之外,国产芯片再突破,再也不用看AMD和NVIDIA的脸色了
  17. Android Things:让你陌生的面包板
  18. LeetCode简单-Python-(13)罗马数字转整数
  19. 进入外包公司之后…………
  20. 爬虫练习-荔枝直播(分享页)

热门文章

  1. Hyper-V下的Linux虚拟机网卡丢失问题原因及解决办法
  2. [转]MySQL数据库优化总结
  3. C#委托Action、ActionT、FuncT、PredicateT
  4. Asp.net(C#)动态生成表格中的按钮和事件响应
  5. SVM原理以及Tensorflow 实现SVM分类(附代码讲了一下原理)
  6. MySQL重要概念图解(重要)
  7. JS的window-location
  8. PHP的composer安装问题
  9. 佳能单反相机二次开发包介绍_家用单反相机什么牌子好
  10. 本地通过域名访问虚拟机的网站部署方法(Nginx)