美文网首页
Spring MVC处理请求流程

Spring MVC处理请求流程

作者: b335eb9201c3 | 来源:发表于2020-01-17 16:40 被阅读0次

    接前面的“SpringMVC启动分析”

    继续……

    作为一个Servlet,请求时从doGet和doPost开始的

    DispatcherServlet的doGet和doPost是从FrameworkServlet继承来的

    d5d02a4bc23561b1709ffff92415f99b.png

    proce***equest()中主要是调用doService()方法,它是在DispatcherServlet中具体实现的

    df8b3de84ba123c0bc41e12571fad849.png

    doService中主要是调用doDispatch方法

    22e87451b49eb9b4cf1af490c0fdd350.png

    51e6a29fd4f6b71a32eb691735e1bd84.png

    这个方法就是SpringMVC处理过程的宏观流程,从这里可以看出大致流程如下:

    (1)判断是否有文件上传,如果有,请求转成MultipartHttpServletRequest

    (2)从HandlerMapping中查找请求对应的Handler,并返回一个HandlerExecutionChain。这个处理器执行链中包含了处理器和拦截器。

    (3)查找Handler对应的HandlerAdapter

    (4)依次调用拦截器的preHandle方法

    (5)通过HandlerAdapter的handle方法去调用处理器的目标方法,并返回ModelAndView对象

    (6)依次调用拦截器的postHandle方法

    (7)渲染视图(找到具体的视图页面,并填充模型数据),并依次调用拦截器的afterCompletion方法

    上面这个过程有几个疑问:

    疑问1:怎么找到HandlerMapping的?

    疑问2:怎么找到HandlerAdapter?为什么要Adapter?

    下面具体来看一下

    怎么找HandlerMapping?

    6ed46e08630e438c792bada38162c97e.png

    这是默认的HandlerMapping和HandlerAdapter组件,这里我们只看其中一种,基于注解的实现

    与之对应的是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter

    先看DefaultAnnotationHandlerMapping

    a0bc7c769cc22d04df65d19bcf46ad27.png

    DefaultAnnotationHandlerMapping间接实现了ApplicationContextAware接口,所以在WebApplicationContext创建完成以后会回调setApplicationContext()方法,而在这个方法中又调用了initApplicationContext()方法,它是在子类中实现的,所以,对应DefaultAnnotationHandlerMapping而言,它最终调用的是AbstractDetectingUrlHandlerMapping中的initApplicationContext()方法。下面看一下它长什么样?

    877a00ba362f9fe400b2a16adc81b387.png

    b9bc2ae5ac89a914eaf11da5d07c5b53.png

    上面两步所做的工作就是找到全部的映射URL,查找的依据如下:

    (1)看Bean上面有没有@RequestMapping注解,如果有,遍历Bean中所有的方法,在方法是同样是找@RequestMapping注解,如果找到了,则两个@RequestMapping注解的value值拼接在一起就是一个url

    (2)如果Bean上面没有@RequestMapping注解,直接在其方法上找,同样返回注解value值

    举个例子:

    1ca79ad36df0a185a7a2ee6155f20522.png

    这个Controller会产生3个url映射

    9143b43c2e6980c61485573fa9fe0732.png

    这样就可以找到所有的映射Url,并以数组形式返回。也就是说,每次返回的String[]中的url对应的处理器是同一个。

    到此为止,我们就知道了,是怎么根据请求uri找到对应的Controller的,原来是因为SpringMVC启动的时候就已经建立好了这种映射关系。

    这里顺带提一句,默认的HandlerMapping并不只是DefaultAnnotationHandlerMapping这一个,还有一个是BeanNameUrlHandlerMapping,它是根据Bean的名字来识别的,以"/"开头的就是。

    f92e93b0db7fa11554159814cb9c3e54.png

    接下来看第2个问题

    HandlerAdapter是干什么的?为什么需要Adapter?

    首先,为什么需要Adapter,明明已经拿到Handler对象了干嘛不直接调用具体的方法呢,还要通过Adapter去调用具体的方法?

    我觉得,有这样几个原原因

    1、屏蔽底层实现的差异和复杂度。创建Controller的方式有很多种,基于注解来创建只是其中一种,不同类型的处理器,有不同类型的Adapter,但最终还是HandlerAdapter。(PS:感觉有点像策略模式呀)

    2、适配不同类型的处理器。这跟第一点很类似,Adapter适配器,就想一个插排一样,可以适配各种插头,HandlerAdapter就是插排,其实现类就是插头。

    41f7d6fa45783037284b5ed21d26b846.png

    接下来,具体看一下AnnotationMethodHandlerAdapter是如何处理的

    5fff7c56c65ab44240ac0e7c08fb3cb8.png

    找Handler中有@RequestMapping注解的方法,通过url匹配到具体的Method,这个Method已经是反射后的Method对象,然后调用。具体步骤其实很复杂,这里不细看了。

    https://blog.51cto.com/5880861/1981945

    相关文章

      网友评论

          本文标题:Spring MVC处理请求流程

          本文链接:https://www.haomeiwen.com/subject/brzczctx.html