专栏首页Java编程指南为什么都说DispatcherServlet是Spring MVC的核心呢?

为什么都说DispatcherServlet是Spring MVC的核心呢?

# 前言

SpringMVC是目前主流的Web MVC框架之一。

本文将分析SpringMVC的核心分发器DispatcherServlet的初始化过程以及处理请求的过程,让读者了解这个入口Servlet的作用。

# DispatcherServlet初始化过程

在分析DispatcherServlet之前,我们先看下DispatcherServlet的继承关系。

HttpSerlvetBean继承自HttpServlet。

HttpServletBean覆写了init方法,对初始化过程做了一些处理。我们来看下init方法到底做了什么:

<servlet>
  <servlet-name>dispatcher</servlet-name>  
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  <load-on-startup>1</load-on-startup>  
  <init-param>
    <param-name>contextConfigLocation</param-name>  
    <param-value>classpath:springConfig/dispatcher-servlet.xml</param-value>  
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>  
  <url-pattern>/</url-pattern>  
</servlet-mapping>

比如上面这段配置,传递了contextConfigLocation参数,之后构造BeanWrapper,这里使用BeanWrapper,有2个理由:

1. contextConfigLocation属性在FrameworkServlet中定义,HttpServletBean中未定义

2. 利用Spring的注入特性,只需要调用setPropertyValues方法就可将contextConfigLocation属性设置到对应实例中,也就是以依赖注入的方式初始化属性。

然后设置DispatcherServlet中的contextConfigLocation属性(FrameworkServlet中定义)为web.xml中读取的contextConfigLocation参数,该参数用于构造SpringMVC容器上下文。

下面看下FrameworkServlet这个类,FrameworkServlet继承自HttpServletBean。

首先来看下该类覆写的initServletBean方法:

接下来看下initWebApplicationContext方法的具体实现逻辑:

这里的根上下文是web.xml中配置的ContextLoaderListener监听器中根据

contextConfigLocation路径生成的上下文。<context-param>
  <param-name>contextConfigLocation</param-name>  
  <param-value>classpath:springConfig/applicationContext.xml</param-value>  
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener>

比如这段配置文件中根据classpath:springConfig/applicationContext.xml下的xml文件生成的根上下文。

最后看下DispatcherServlet。

DispatcherServlet覆写了FrameworkServlet中的onRefresh方法:

很明显,initStrategies方法内部会初始化各个策略接口的实现类。

总结一下各个Servlet的作用:

1. HttpServletBean

主要做一些初始化的工作,将web.xml中配置的参数设置到Servlet中。比如servlet标签的子标签init-param标签中配置的参数。

2. FrameworkServlet

将Servlet与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类上下文,既web.xml中配置的ContextLoaderListener监听器初始化的容器上下文。

3. DispatcherServlet

初始化各个功能的实现类。比如异常处理、视图处理、请求映射处理等。

# DispatcherServlet处理请求过程

在分析DispatcherServlet处理请求过程之前,我们回顾一下Servlet对于请求的处理。

HttpServlet提供了service方法用于处理请求,service使用了模板设计模式,在内部对于http get方法会调用doGet方法,http post方法调用doPost方法...........

进入processRequest方法看下:

其中注册的监听器类型为ApplicationListener接口类型。

继续看DispatcherServlet覆写的doService方法:

最终就是doDispatch方法。

doDispatch方法功能简单描述一下:

首先根据请求的路径找到HandlerMethod(带有Method反射属性,也就是对应Controller中的方法),然后匹配路径对应的拦截器,有了HandlerMethod和拦截器构造个HandlerExecutionChain对象。HandlerExecutionChain对象的获取是通过HandlerMapping接口提供的方法中得到。有了HandlerExecutionChain之后,通过HandlerAdapter对象进行处理得到ModelAndView对象,HandlerMethod内部handle的时候,使用各种HandlerMethodArgumentResolver实现类处理HandlerMethod的参数,使用各种HandlerMethodReturnValueHandler实现类处理返回值。最终返回值被处理成ModelAndView对象,这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理。

# 总结

本文分析了SpringMVC入口Servlet -> DispatcherServlet的作用,其中分析了父类HttpServletBean以及FrameworkServlet的作用。

SpringMVC的设计与Struts2完全不同,Struts2采取的是一种完全和Web容器隔离和解耦的机制,而SpringMVC就是基于最基本的request和response进行设计。

文中难免有错误,希望读者能够指明出来。

# 参考资料

  • http://my.oschina.net/lichhao/blog/102315
  • http://my.oschina.net/lichhao/blog/104943
  • http://jinnianshilongnian.iteye.com/blog/1602617

本文分享自微信公众号 - Java编程指南(JavaXxzyfx),作者:Java编程指南

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Maven常用命令

      如果你还再用的话,那你就out了,现代人都用mvn archetype:generate了,它将创建项目这件枯燥的事更加人性化,你再也不需要记那么多的arc...

    Java编程指南
  • 外国大神整理的 2019 年 Java 开发路线图,值得学习!

    许多Java开发人员都希望通过某种Java成长路线图,来解答有关:该学习哪些技术,使用哪些工具以及框架之类的问题。

    Java编程指南
  • Maven 常用配置

    我需要让整个项目统一字符集编码,就需要设定<project.build.sourceEncoding>UTF-8</project.build.sourceEn...

    Java编程指南
  • 2020 年 9 大顶级 Java 框架出炉!

    自 1995 年推出以来,Java 已被 134861 个网站(如ESPN,SnapDeal,阿里巴巴等)使用。在 24 年的发展历程中,Java 已证明自己是...

    黄泽杰
  • 2020 年国外 9 个顶级的 Java 框架,你知道几个?

    https://towardsdatascience.com/9-top-java-frameworks-for-2020-1cc9d3c21f4c

    纯洁的微笑
  • AS3和JS通信

    注意:先调用ExternalInterface.addCallback,再调用ExternalInterface.call

    py3study
  • Springboot2.0 + Kotlin自定义json序列化不返回null字段的方法

    飞奔去旅行
  • 史上最详细nodejs版本管理器nvm的安装与使用(附注意事项和优化方案)

    Java中文社群_老王
  • 史上最详细nodejs版本管理器nvm的安装与使用(附注意事项和优化方案)

    使用场景 在Node版本快速更新迭代的今天,新老项目使用的node版本号可能已经不相同了,node版本更新越来越快,项目越做越多,node切换版本号的需求越来越...

    Java中文社群_老王
  • 给Java程序猿们推荐一些值得一看的好书

    "学习的最好途径就是看书",这是我自己学习并且小有了一定的积累之后的第一体会。个人认为看书有两点好处:

    Java后端工程师

扫码关注云+社区

领取腾讯云代金券