SpringMvc请求调用源码分析
DispatcherServlet继承关系如下:
DispatcherServlet→FrameworkServlet→HttpServletBean→HttpServlet
一个请求过来,先是会进入HttpServlet的Service()方法:
此处就以doGet方法进行分析:
FrameworkServlet重写了doGet方法,所以最终会调用该类的doGet方法
主要看这个processRequest()方法:
注:后面深入发现,上面的操作将session塞入当前请求线程是错误的,之前以为是在这边塞入的,看了tomcat源码,其实是tomcat会在请求过来的时候根据cookie中的jsessionid自动将关联的session绑定到HttpServletRequest中,而不是在这里,这边就是构造一个上下文线程安全实例绑定一下。
上述分析主要是初始化request请求的一些上下文信息,比如像session这种就是在这个地方塞入request的。
初始完上下文request后,会调用doService()方法:
DispatcherServlet重写了该方法:
进入doDispatch()方法详解:
进入getHandler()方法:
可以看到springboot启动时装载的全部handlerMapping都保存在List<HandlerMapping> handlerMappings中。这里遍历handlerMappings中所有handlerMapping,直到找到请求对应的Mapping并返回执行立链HandlerExecutionChain。因为是@RequestMapping映射,所以遍历到handlerMappings[1]==RequestMappingHandlerMapping可以找到对应执行链。
下边直接步进到RequestMappingHandlerMapping其继承自AbstractHandlerMapping。
RequestMappingHandlerMapping初始化时注册@RequestMapping映射
RequestMappingHandlerMapping成员变量
getHandler()方法:
HandlerExecutionChain对象是封装了请求匹配的拦截器调用(如果匹配到的话)和具体的handlerMethod对象调用。
进入getHandlerInternal方法(AbstractHandlerMethodMapping类):
进入lookupHandlerMethod()方法
这里会根据请求的必填参数,请求的头部参数等等信息匹配相关的handlerMethod,就是根据url参数信息校验是否有对应的handlerMethod。
接下来看getHandlerExecutionChain()方法
*springmvc拦截器不同于aop因为存在统一入口dispatchservlet所以不需要动态代理*.
SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理。哪不难想到我们在执行controller之前做某些动作,执行完毕做某些动作,render完成做某些动作。SpringMVC的拦截器对应提供了三个preHandle,postHandle,afterCompletion方法。只需在三个方法内写我们需要的逻辑就行,多了都是废话,还是代码实在。
获取handlerExecutionChain不过多叙述了。
接下来看看
根据handlerMapping类型获取对应的handlerAdapter
介绍一下几种适配器对应的处理器以及这些处理器的作用:
1. AnnotationMethodHandlerAdapter主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器
2. HttpRequestHandlerAdapter主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。
3.SimpleControllerHandlerAdapter是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器,比如我们经常自己写的Controller来继承MultiActionController.
4.SimpleServletHandlerAdapter是Servlet处理适配器,适配实现了Servlet接口或Servlet的子类的处理器,我们不仅可以在web.xml里面配置Servlet,其实也可以用SpringMVC来配置Servlet,不过这个适配器很少用到,而且SpringMVC默认的适配器没有他,默认的是前面的三种。
接下来看具体的方法调用过程
AnnotationMethodHandlerAdapter(spring2.5之前用的是这个,这里就看看是干嘛用的):
RequestMappingHandlerAdapter(正常调用就是用的这个适配器,父类是AbstractHandlerMethodAdapter)
关注一下下面的这个synchronizeOnSession这个锁,回对应web.xml里这个配置:
重头戏:invokeHandlerMethod:
1 | protected ModelAndView invokeHandlerMethod(HttpServletRequest request, |
ServletInvocableHandlerMethod.invokeAndHandle()
InvocableHandlerMethod.invokeForRequest()
最后放一张springmvc请求流程图:
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。