SpringMVC 执行流程及源码解析

SpringMVC

在SpringMVC中主要是围绕着DispatcherServlet来设计,可以把它当做指挥中心。这里先说明一下SpringMVC文档给出的执行流程,然后是我们稍微具体的执行流程,最后是流程大致的源码跟踪。关于很很很详细的源码解析,这里暂先不做。

官方文档中的流程

首先看下SpringMVC文档上给的流程图:

SpringMVC 执行流程及源码解析_第1张图片

这张图片给了我们大概的执行流程:

  1. 用户请求首先发送到前端控制器DispatcherServlet,DispatcherServlet根据请求的信息来决定使用哪个页面控制器Controller(也就是我们通常编写的Controller)来处理该请求。找到控制器之后,DispatcherServlet将请求委托给控制器去处理。
  2. 接下来页面控制器开始处理用户请求,页面控制器会根据请求信息进行处理,调用业务层等等,处理完成之后,会把结果封装成一个ModelAndView返回给DispatcherServlet。
  3. 前端控制器DispatcherServlet接到页面控制器的返回结果后,根据返回的视图名选择相应的试图模板,并根据返回的数据进行渲染。
  4. 最后前端控制器DispatcherServlet将结果返回给用户。

更具体的流程

上面只是总体流程,接下来我们稍微深入一点,看下更具体的流程,这里没有图,只有步骤解析:

  1. 用户请求发送到前端控制器
    DispatcherServlet。

  2. 前端控制器 DispatcherServlet 接收到请求后,DispatcherServlet 会使用
    HandlerMapping 来处理,HandlerMapping 会查找到具体进行处理请求的 Handler 对象。

  3. HandlerMapping 找到对应的 Handler 之后,并不是返回一个 Handler 原始对象,而是一个 Handler
    执行链,在这个执行链中包括了拦截器和处理请求的 Handler。HandlerMapping 返回一个执行链给
    DispatcherServlet。

  4. DispatcherServlet 接收到执行链之后,会调用 Handler 适配器去执行Handler。

  5. Handler 适配器执行完成 Handler(也就是我们写的 Controller)之后会得到一个
    ModelAndView,并返回给 DispatcherServlet。

  6. DispatcherServlet 接收到 Handler 适配器返回的 ModelAndView
    之后,会根据其中的视图名调用视图解析器。

  7. 视图解析器根据逻辑视图名解析成一个真正的 View 视图,并返回给 DispatcherServlet。

  8. DispatcherServlet 接收到视图之后,会根据上面的 ModelAndView 中的 model
    来进行视图中数据的填充,也就是所谓的视图渲染。

  9. 渲染完成之后,DispatcherServlet 就可以将结果返回给用户了。

源码

DispatcherServlet是一个Servlet,我们知道在Servlet在处理一个请求的时候会交给service方法进行处理,这里也不例外,DispatcherServlet继承了FrameworkServlet,首先进入FrameworkServlet的service方法:

SpringMVC 执行流程及源码解析_第2张图片

HttpServlet中会根据请求类型的不同分别调用doGet或者doPost等方法,FrameworkServlet中已经重写了这些方法,在这些方法中会调用processRequest进行处理,在processRequest中会调用doService方法,这个doService方法就是在DispatcherServlet中实现的。

下面就看下DispatcherServlet中的doService方法的实现。

请求到达DispatcherServlet

doService方法:

SpringMVC 执行流程及源码解析_第3张图片

SpringMVC 执行流程及源码解析_第4张图片

DispatcherServlet开始真正的处理,doDispatch方法:

SpringMVC 执行流程及源码解析_第5张图片

SpringMVC 执行流程及源码解析_第6张图片

SpringMVC 执行流程及源码解析_第7张图片
可以看到大概的步骤还是按照我们上面分析的走的。

查找请求对应的Handler对象

对应着这句代码mappedHandler = getHandler(processedRequest, false);,看下具体的getHandler方法:

这里写图片描述

继续往下看getHandler:
SpringMVC 执行流程及源码解析_第8张图片

继续往下看getHandler,在AbstractHandlerMapping类中:

SpringMVC 执行流程及源码解析_第9张图片

根据requrst获取handler

首先看下根据requrst获取handler步骤getHandlerInternal方法,在AbstractHandlerMethodMapping中:

SpringMVC 执行流程及源码解析_第10张图片

看下根据路径寻找handler的方法lookupHandlerMethod:
SpringMVC 执行流程及源码解析_第11张图片

SpringMVC 执行流程及源码解析_第12张图片

获取默认Handler

如果上面没有获取到Handler,就会获取默认的Handler。如果还获取不到就返回null。

处理String类型的Handler

如果上面处理完的Handler是String类型的,就会根据这个handlerName获取bean。

封装Handler执行链

上面获取完Handler,就开始封装执行链了,就是将我们配置的拦截器加入到执行链中去,getHandlerExecutionChain:
SpringMVC 执行流程及源码解析_第13张图片

获取对应请求的Handler适配器

getHandlerAdapter:

SpringMVC 执行流程及源码解析_第14张图片

缓存的处理

也就是对last-modified的处理

执行拦截器的preHandle方法

就是遍历所有的我们定义的interceptor,执行preHandle方法

使用Handler适配器执行当前的Handler

ha.handle执行当前Handler,我们这里使用的是RequestMappingHandlerAdapter,首先会进入AbstractHandlerMethodAdapter的handle方法:
这里写图片描述

handleInternal方法,在RequestMappingHandlerAdapter中:

SpringMVC 执行流程及源码解析_第15张图片

组装默认视图名称

前缀和后缀名都加上

执行拦截器的postHandle方法

遍历intercepter的postHandle方法。

处理最后的结果,渲染之类的

processDispatchResult方法:
SpringMVC 执行流程及源码解析_第16张图片

SpringMVC 执行流程及源码解析_第17张图片
重点看下render方法,进行渲染:

SpringMVC 执行流程及源码解析_第18张图片

view.render就是进行视图的渲染,然后跳转页面等处理。

到这里大概的流程就走完了。其中涉及到的东西还有很多,暂先不做详细处理。

你可能感兴趣的:(spring)