转自:http://blog.csdn.net/shi1122/article/details/8041017

(转移位置了,时光隧道:http://www.jmatrix.org/spring/501.html

在之前的“spring MVC实现分析——初始化”中分析了spring mvc的初始化过程,接下来将分析其请求处理过程。

在找请求处理的入口时,我们需要先知道Servlet的编程规范,对应不同的请求(如POST、GET等)的实现方法在FrameworkServlet 中,分别是doPost、doGet等,看这一系列方法的具体实现可以知道,请求的处理跳转到了processRequest函数中,最终进入 DispatcherServlet的doService函数,详细的流程如:

上面的时序图展示了详细的请求处理流程,其中最重要的是doDispatch函数,其中包含了整个的处理逻辑,

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. HttpServletRequest processedRequest = request;
  3. HandlerExecutionChain mappedHandler = null;
  4. boolean multipartRequestParsed = false;
  5. WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request);
  6. try {
  7. ModelAndView mv = null;
  8. Exception dispatchException = null;
  9. try {
  10. processedRequest = checkMultipart(request);
  11. multipartRequestParsed = processedRequest != request;
  12. // Determine handler for the current request.
  13. mappedHandler = getHandler(processedRequest, false);
  14. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  15. noHandlerFound(processedRequest, response);
  16. return;
  17. }
  18. // Determine handler adapter for the current request.
  19. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  20. // Process last-modified header, if supported by the handler.
  21. ……
  22. try {
  23. // Actually invoke the handler.
  24. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  25. }
  26. finally {
  27. if (asyncManager.isConcurrentHandlingStarted()) {
  28. return;
  29. }
  30. }
  31. applyDefaultViewName(request, mv);
  32. mappedHandler.applyPostHandle(processedRequest, response, mv);
  33. }
  34. catch (Exception ex) {
  35. dispatchException = ex;
  36. }
  37. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  38. }
  39. ……
  40. }
  41. finally {
  42. ……
  43. }
  44. }

首先我们先看HandlerExecutionChain这个类中有些什么东西,

  1. public class HandlerExecutionChain {
  2. private final Object handler;
  3. private HandlerInterceptor[] interceptors;
  4. private List<HandlerInterceptor> interceptorList;
  5. ……
  6. }

这里面有两个关键的东西handler与interceptors,也即处理器对象与拦截器链表,联系到我们实际的编程,handler有可能是两种东
西:(1)controller类对象;(2)controller中的方法对象(用的术语可能不太准确……)。而interceptors也即我们定义
拦截器对象列表,如果说想在请求被处理之前做点什么就会弄一个。明白了这一点,再来看看在doDispatch函数中如果获得
HandlerExecutionChain对象mappedHandler。

可以看到其实现在getHandler方法中:

  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2. for (HandlerMapping hm : this.handlerMappings) {
  3. ……
  4. HandlerExecutionChain handler = hm.getHandler(request);
  5. if (handler != null) {
  6. return handler;
  7. }
  8. }
  9. return null;
  10. }

函数的实现非常简单:遍历已注册的HandlerMapping列表,通过HandlerMapping对象的getHandler函数获取
HandlerExecutionChain对象。至于HandlerMapping中的getHandler函数如何获取
HandlerExecutionChain需要的处理器与拦截器,我只能说过程是繁琐的,原理是简单的,对于处理器对象(handler)根据不同的
Mapping实现,其可以根据bean配置中的urlPath或者是方法的注解来寻找,这里不再细说。

顺着doDispatch函数的执行流程往下看,紧接着其通过getHandlerAdapter函数获得HandlerAdapter对象ha,然后就是又要重点照顾的一个调用:

  1. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

随着调用HandlerAdapter的handle函数,Spring
MVC便开始要真的“干实事”了,所谓的“干实事”也即开始调用执行我们编写的controller(控制逻辑)了。这里以两个
HandlerAdapter的实现HttpRequestHandlerAdapter与
AnnotationMethodHandlerAdapter来分析这个处理流程,在之前的一篇文章“Spring
MVC实现分析——初始化过程
”中有提到我自己的一个Spring MVC程序配置,以此为准进行展开:

HttpRequestHandlerAdapter的实现是最容易理解的,因为其handle的实现就是调用了处理器(handler)对象的
handleRequest函数,借助F4看看Controller的继承体系,再看看AbstractController中
handleRequest函数的实现,结合自己菜鸟时期编写的Spring MVC “hello world程序”,你就会有恍然大悟的感觉⊙﹏⊙!

至于AnnotationMethodHandlerAdapter,其实现原理也是很容易理解的,我们已经知道其就是针对采用注解方式的方法映射的,实际应用中如:

  1. @RequestMapping(method=RequestMethod.GET,value="/homeController.xhtml")
  2. protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
  3. HttpServletResponse arg1) throws Exception {
  4. ……
  5. }

所以其handle的实现就是通过Java的反射机制找到注解对应的处理方法,并调用完成控制逻辑的执行。

此时,让我们再次回到doDispatch的处理流程上来,在经过handle的“干实事”后,我们得到了ModelAndView对象,也即视图对象,
很自然接下来的就是视图的渲染与展示了,这也是我们最后要分析的一个点。其入口是doDispatch中的一个函数调用:

    1. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

Spring MVC源码分析(续)——请求处理的更多相关文章

  1. 精尽Spring MVC源码分析 - 寻找遗失的 web.xml

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  2. 精尽Spring MVC源码分析 - 调式环境搭建

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  3. 精尽Spring MVC源码分析 - 文章导读

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  4. 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  5. 精尽Spring MVC源码分析 - 一个请求的旅行过程

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  6. 精尽Spring MVC源码分析 - MultipartResolver 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  7. 精尽Spring MVC源码分析 - HandlerMapping 组件(一)之 AbstractHandlerMapping

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  8. 精尽Spring MVC源码分析 - HandlerMapping 组件(二)之 HandlerInterceptor 拦截器

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  9. 精尽Spring MVC源码分析 - HandlerMapping 组件(三)之 AbstractHandlerMethodMapping

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  10. 精尽Spring MVC源码分析 - HandlerMapping 组件(四)之 AbstractUrlHandlerMapping

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

随机推荐

  1. 界面编程模仿篇(QQ登录界面逼真篇)

    写了好多天的爬虫,偷空前前后后用了两天的时间(排除吃饭睡觉)写完了这个QQ登录界面,看起来还凑和着吧,如果是的大神的,莫见笑,纯属业余作品,废话先不多说,截图如下,其中第二幅图片中的红色方框部份有待完 ...

  2. PHP环境配置综合篇

    1.WNMP: http://www.wnmp.com.cn/     En: https://www.getwnmp.org/ 2.xampp:https://www.apachefriends.o ...

  3. 数字证书KeyTool使用(第二篇)

    http://my.oschina.net/frankies/blog/344914 J2SDK提供了keytool命令行工具,可以根据指定的参数来创建数字证书.生成的证书或证书库默认保存在命令行当前 ...

  4. sso笔记

    C:\Windows\System32\drivers\etc\hosts SSO:单点登录 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/&q ...

  5. 通讯录改造——MVC设计模式

    将之前用servlet写的程序转化为jsp+servlet的简单的MVC的三层结构.项目中程序的包如图 首先是实体对象: package com.contactSystem.entiey; publi ...

  6. JMeter的基本介绍和入门

    1. 介绍 JMeter是Apache组织的开放源代码项目,能做功能测试和性能测试.它能够对HTTP和FTP服务器进行压力和性能测试,也可以对任何数据库进行同样的测试(通过JDBC),还能以多种形式展 ...

  7. 【转】Android Studio Essential Training

    http://ask.android-studio.org/?/explore/category-video Android Studio Essential Training内容包括:- Andro ...

  8. 关闭对话框,OnClose和OnCancel

    我们知道,在对话框中,屏蔽ESC键自己主动退出能够选择重载OnCancel为哑函数的方法: void CXXXXDlg::OnCancel()      {         // TODO: Add ...

  9. [Node.js] Node.js Buffers

    >> node >>fs.readFile('finnish.txt', function(err,data){ console.log(data); }); // Outpu ...

  10. UVA10518 - How Many Calls?(矩阵高速幂)

    UVA10518 - How Many Calls?(矩阵高速幂) 题目链接 题目大意:给你fibonacci数列怎么求的.然后问你求f(n) = f(n - 1) + f(n - 2)须要多少次调用 ...