Spring MVC 原理探秘-一个请求的旅行过程

【每日条语】当你停下脚步的时候,不要忘了别人还在奔跑。不怕万人阻挡在前方,只怕自己先行投降。

最近个大长,中厂开始人才盘点,人才升级啦,经济不景气最后还是反应互联网上来了,今天跟大家分享一个“一个请求的旅行过程”,可能面试的时候经常问,关注我的人可能最近也在找工作,与大家一起分享一下吧!

1:一个请求的旅行过程

在探索更深层次的原理之前,我们先来了解一下 Spring MVC 是怎么处理请求的。弄懂了这个流程后,才能更好的理解具体的源码。这里我把 Spring MVC 处理请求的流程图画了出来,一起看一下吧:

Spring MVC 原理探秘-一个请求的旅行过程

如上,每一个重要的步骤上面都有编号。我先来简单分析一下上面的流程,然后再向大家介绍图中出现的一些组件。我们从第一步开始,首先,用户的浏览器发出了一个请求,这个请求经过互联网到达了我们的服务器。Servlet 容器首先接待了这个请求,并将该请求委托给 DispatcherServlet 进行处理。接着 DispatcherServlet 将该请求传给了处理器映射组件 HandlerMapping,并获取到适合该请求的拦截器和处理器。在获取到处理器后,DispatcherServlet 还不能直接调用处理器的逻辑,需要进行对处理器进行适配。处理器适配成功后,DispatcherServlet 通过处理器适配器 HandlerAdapter 调用处理器的逻辑,并获取返回值 ModelAndView。之后,DispatcherServlet 需要根据 ModelAndView 解析视图。解析视图的工作由 ViewResolver 完成,若能解析成功,ViewResolver 会返回相应的视图对象 View。在获取到具体的 View 对象后,最后一步要做的事情就是由 View 渲染视图,并将渲染结果返回给用户。

以上就是 Spring MVC 处理请求的全过程,上面的流程进行了一定的简化,比如拦截器的执行时机就没说。不过这并不影响大家对主过程的理解。下来来简单介绍一下图中出现的一些组件:

Spring MVC 原理探秘-一个请求的旅行过程

从上面的流程中可以看出,Spring MVC 对各个组件的职责划分的比较清晰。DispatcherServlet 负责协调,其他组件则各自做分内之事,互不干扰。经过这样的职责划分,代码会便于维护。

2:追根溯源之 Servlet

向大家介绍一下 Servlet,为什么要介绍 Servlet 呢?原因不难理解,Spring MVC 是基于 Servlet 实现的。所以要分析 Spring MVC,首先应追根溯源,弄懂 Servlet。Servlet 是 J2EE 规范之一,在遵守该规范的前提下,我们可将 Web 应用部署在 Servlet 容器下。这样做的好处是什么呢?我觉得可使开发者聚焦业务逻辑,而不用去关心 HTTP 协议方面的事情。

Spring MVC 原理探秘-一个请求的旅行过程

如果我们写的 Web 应用不大,不夸张的说,项目中对 HTTP 提供支持的代码会比业务代码还要多,这岂不是得不偿失。当然,在现实中,有现成的框架可用,并不需要自己造轮子。如果我们基于 Servlet 规范实现 Web 应用的话,HTTP 协议的处理过程就不需要我们参与了。这些工作交给 Servlet 容器就行了,我们只需要关心业务逻辑怎么实现即可。

3:Servlet 与 ServletConfig

Spring MVC 原理探秘-一个请求的旅行过程

init 方法会在容器启动时由容器调用,也可能会在 Servlet 第一次被使用时调用,调用时机取决 load-on-start 的配置。容器调用 init 方法时,会向其传入一个 ServletConfig 参数。ServletConfig 是什么呢?顾名思义,ServletConfig 是一个和 Servlet 配置相关的接口。举个例子说明一下,我们在配置 Spring MVC 的 DispatcherServlet 时,会通过 ServletConfig 将配置文件的位置告知 DispatcherServlet。

Servlet 中的 service 方法用于处理请求。当然,一般情况下我们不会直接实现 Servlet 接口,通常是通过继承 HttpServlet 抽象类编写业务逻辑的。Servlet 中接口不多,也不难理解,这里就不多说了。下面我们来看看 ServletConfig 接口定义,如下:

Spring MVC 原理探秘-一个请求的旅行过程

3:DispatcherServlet 族谱

DispatcherServlet 是 Spring MVC 的核心,一起看看继承关系图

Spring MVC 原理探秘-一个请求的旅行过程

3.1:EnvironmentCapable

EnvironmentCapable 仅包含一个方法定义 getEnvironment,通过该方法可以获取到环境变量对象。我们可以将 EnvironmentCapable 和 EnvironmentAware 接口配合使用,比如下面的实例:

Spring MVC 原理探秘-一个请求的旅行过程

3.2:HttpServletBean

HttpServletBean 是 HttpServlet 抽象类的简单拓展。HttpServletBean 覆写了父类中的无参 init 方法,并在该方法中将 ServletConfig 里的配置信息设置到子类对象中,比如 DispatcherServlet。

3.3: FrameworkServlet

FrameworkServlet 是 Spring Web 框架中的一个基础类,该类会在初始化时创建一个容器。同时该类覆写了 doGet、doPost 等方法,并将所有类型的请求委托给 doService 方法去处理。doService 是一个抽象方法,需要子类实现。

3.4: DispatcherServlet

DispatcherServlet 主要的职责相信大家都比较清楚了,即协调各个组件工作。除此之外,DispatcherServlet 还有一个重要的事情要做,即初始化各种组件,比如 HandlerMapping、HandlerAdapter 等。

好像基本跟大家讲概念最后给大家贴一张认为比较简单的图:

Spring MVC 原理探秘-一个请求的旅行过程

4:小结

"冬天来了,春天还会远吗?"-雪莱

即使你处在寒冷的冬天,只要你心中有光,你就能闻到春天的气息;

即使你被困境所困,只要你心中有光,头顶的乌云总会被它所穿透;

即使你被挫折和失败打翻一百次,只要你心中有光,你同样可以一百零一 次站起来。

把苦涩的微笑留给昨天,用不屈的毅力和信念赢得未来!

相信一切会好起来的!!!!


分享到:


相關文章: