标签:springmvc
接前面的“SpringMVC启动分析”
继续……
作为一个Servlet,请求时从doGet和doPost开始的
DispatcherServlet的doGet和doPost是从FrameworkServlet继承来的
processRequest()中主要是调用doService()方法,它是在DispatcherServlet中具体实现的
doService中主要是调用doDispatch方法
这个方法就是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?
这是默认的HandlerMapping和HandlerAdapter组件,这里我们只看其中一种,基于注解的实现
与之对应的是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter
先看DefaultAnnotationHandlerMapping
DefaultAnnotationHandlerMapping间接实现了ApplicationContextAware接口,所以在WebApplicationContext创建完成以后会回调setApplicationContext()方法,而在这个方法中又调用了initApplicationContext()方法,它是在子类中实现的,所以,对应DefaultAnnotationHandlerMapping而言,它最终调用的是AbstractDetectingUrlHandlerMapping中的initApplicationContext()方法。下面看一下它长什么样?
上面两步所做的工作就是找到全部的映射URL,查找的依据如下:
(1)看Bean上面有没有@RequestMapping注解,如果有,遍历Bean中所有的方法,在方法是同样是找@RequestMapping注解,如果找到了,则两个@RequestMapping注解的value值拼接在一起就是一个url
(2)如果Bean上面没有@RequestMapping注解,直接在其方法上找,同样返回注解value值
举个例子:
这个Controller会产生3个url映射
这样就可以找到所有的映射Url,并以数组形式返回。也就是说,每次返回的String[]中的url对应的处理器是同一个。
到此为止,我们就知道了,是怎么根据请求uri找到对应的Controller的,原来是因为SpringMVC启动的时候就已经建立好了这种映射关系。
这里顺带提一句,默认的HandlerMapping并不只是DefaultAnnotationHandlerMapping这一个,还有一个是BeanNameUrlHandlerMapping,它是根据Bean的名字来识别的,以"/"开头的就是。
接下来看第2个问题
HandlerAdapter是干什么的?为什么需要Adapter?
首先,为什么需要Adapter,明明已经拿到Handler对象了干嘛不直接调用具体的方法呢,还要通过Adapter去调用具体的方法?
我觉得,有这样几个原原因
1、屏蔽底层实现的差异和复杂度。创建Controller的方式有很多种,基于注解来创建只是其中一种,不同类型的处理器,有不同类型的Adapter,但最终还是HandlerAdapter。(PS:感觉有点像策略模式呀)
2、适配不同类型的处理器。这跟第一点很类似,Adapter适配器,就想一个插排一样,可以适配各种插头,HandlerAdapter就是插排,其实现类就是插头。
接下来,具体看一下AnnotationMethodHandlerAdapter是如何处理的
找Handler中有@RequestMapping注解的方法,通过url匹配到具体的Method,这个Method已经是反射后的Method对象,然后调用。具体步骤其实很复杂,这里不细看了。
到此为止,请求处理部分就算是完结了~~~
本文出自 “不要乱摸” 博客,请务必保留此出处http://5880861.blog.51cto.com/5870861/1981945
标签:springmvc
原文地址:http://5880861.blog.51cto.com/5870861/1981945