spring · 27 4 月, 2021 0

DispatcherServerlet 实现原理

DispatcherServlet

类图结构

DispatcherServlet的工作大致分为两个部分

  1. 初始化Servlet, 由initServletBean()启动, 通过initWebApplicationContext()方法最终调用DispatcherServletinitStrategies()方法, 在这个方法中, 主要完成了对容器中的其他组件的初始化,例如handlerMapping,ViewResolver等。

  2. 是对Http请求的处理, 作为一个Sevlet, 最终会调用到doGetdoPost方法, 经过FrameworkServlet方法的processRequest()方法简单处理之后, 会调用到DispatcherServletdoService()方法。

WEB中的双亲委派模型

DispatcherServlet本身也是一个Servlet的实例, 因此, DispatcherServlet的初始化, 实际上跟Servlet初始化一致,在SpringMVC原理中介绍了ContextLoader的加载过程, 会在ServletContext中绑定ROOT容器,那么在Servlet中也有自己的WebApplicationContext的实现, 并且都是ROOT容器的子容易, 在IOC中, 我们知道了在getBean操作中, 会先从父容器中获取对应的bean信息,因此在ROOT中的bean可以在各个子容器共享。

NOTE: 每一个单独的Servlet都可以拥有自己的WebApplicationContext的容器,他们共享一个ROOT的容器。

加载流程

  • HttpServletBean中执行init方法

  • FrameworkServlet中, 初始化当前Servlet的WebApplicationContext的容器, 并将ROOT设置为父容器

  • DispatcherServlet中执行initStrategies()方法, 初始化mvc中的容器控件

initStrategies中初始化那些东西?

  • 初始化MultipartResolver实例

  • 初始化LocaleResolver实例

  • 初始化ThemeResolver实例

  • 初始化handlerMapping实例

  • 初始化HandlerAdapter实例

  • 初始化HandlerExceptionResolver实例

  • 初始化RequestToViewNameTranslator实例

  • 初始化ViewResolver实例

HandlerMapping

从上面我们知道, 在DispatcherServlet初始化的时候, 会从容器中寻找handlerMapping的子类, 作为当前的HandlerMappings的列表, 如果当前的容器中没有配置, 则使用DispatcherServlet.properties的配置文件中获取默认的配置.

HandlerMapping在DispatcherServlet中对应这个列表, 并且是按照顺序排列的,并且这些 HandlerMapping存储着http的请求数据, 这里的每个HandlerMapping都持有者一个URLController的映射关系, Spring MVC中提供了很多的HandlerMapping的实现,具体如下图:

getHandler

getHandler的方法实际返回的是一个HandlerExecutionChain的对象, 这个对象不仅包含了HandlerMapping的本身,同时也包含了http interceptors的拦截器的对象, 这些HandlerMappings可以通过Ordered的进行排序, priority越低, 则执行的优先级越高, 如果没有设置, 则具有最低执行优先级

SimpleUrlHandlerMapping

该类是HandlerMapping的实现类, 实现了URLController的映射关系, 通过registerHandlers()方法实现urlhanlder之间的映射关系,最终关系维护在AbstractUrlMapping的类中, 通过Map来进行实现。

DispatcherServlet的请求分发

View

View主要通过视图的渲染, 这里的渲染包含了生成View的对象, 通过Viewrender的方法实现渲染。