本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制。通过源码我们可以知道从客户端发送一个URL请求给springMvc开始,到返回数据给客户端期间是怎么运转的。

1、用户请求处理过程:

1、用户发送请求时会先从DispathcherServler的doService方法开始,在该方法中会将ApplicationContext、localeResolver、themeResolver等对象添加到request中,紧接着就是调用doDispatch方法:

源码:

  1. protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
  2. if (logger.isDebugEnabled()) {
  3. String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
  4. logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
  5. " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
  6. }
  7. // Keep a snapshot of the request attributes in case of an include,
  8. // to be able to restore the original attributes after the include.
  9. Map<String, Object> attributesSnapshot = null;
  10. if (WebUtils.isIncludeRequest(request)) {
  11. attributesSnapshot = new HashMap<String, Object>();
  12. Enumeration<?> attrNames = request.getAttributeNames();
  13. while (attrNames.hasMoreElements()) {
  14. String attrName = (String) attrNames.nextElement();
  15. if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
  16. attributesSnapshot.put(attrName, request.getAttribute(attrName));
  17. }
  18. }
  19. }
  20. // Make framework objects available to handlers and view objects.
  21. <strong>request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
  22. request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
  23. request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
  24. request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());</strong>
  25. FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
  26. if (inputFlashMap != null) {
  27. request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
  28. }
  29. request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
  30. request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
  31. try {
  32. <strong>doDispatch(request, response);</strong>
  33. }
  34. finally {
  35. if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
  36. return;
  37. }
  38. // Restore the original attribute snapshot, in case of an include.
  39. if (attributesSnapshot != null) {
  40. restoreAttributesAfterInclude(request, attributesSnapshot);
  41. }
  42. }
  43. }

doDispatch方法就是处理用户请求的方法。

2、进入该方法后首先会检查该请求是否是文件上传的请求(校验的规则是是否是post并且contenttType是否为multipart/为前缀)即调用的是checkMultipart方法;如果是的将request包装成MultipartHttpServletRequest。见源码:

doDispatch:

  1. processedRequest = checkMultipart(request);

checkMultipart:

  1. protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
  2. if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
  3. if (request instanceof MultipartHttpServletRequest) {
  4. logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, " +
  5. "this typically results from an additional MultipartFilter in web.xml");
  6. }
  7. else if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) instanceof MultipartException) {
  8. logger.debug("Multipart resolution failed for current request before - " +
  9. "skipping re-resolution for undisturbed error rendering");
  10. }
  11. else {
  12. return this.multipartResolver.resolveMultipart(request);
  13. }
  14. }
  15. // If not returned before: return original request.
  16. return request;
  17. }

3、然后调用getHandler方法来匹配每个HandlerMapping对象,如果匹配成功会返回这个Handle的处理链HandlerExecutionChain对象,在获取该对象的内部其实也获取我们自定定义的拦截器,并执行了其中的方法

见源码:

doDispatch:

  1. HandlerExecutionChain mappedHandler = null;
  2. mappedHandler = getHandler(processedRequest);

getHandler方法:

  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2. for (HandlerMapping hm : this.handlerMappings) {
  3. if (logger.isTraceEnabled()) {
  4. logger.trace(
  5. "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
  6. }
  7. HandlerExecutionChain handler = hm.getHandler(request);
  8. if (handler != null) {
  9. return handler;
  10. }
  11. }
  12. return null;
  13. }
  1. hm.getHandler方法:
  1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2. Object handler = getHandlerInternal(request);
  3. if (handler == null) {
  4. handler = getDefaultHandler();
  5. }
  6. if (handler == null) {
  7. return null;
  8. }
  9. // Bean name or resolved handler?
  10. if (handler instanceof String) {
  11. String handlerName = (String) handler;
  12. handler = getApplicationContext().getBean(handlerName);
  13. }
  14. return getHandlerExecutionChain(handler, request);
  15. }

getHandlerExecutionChain:

  1. protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
  2. HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
  3. (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
  4. chain.addInterceptors(getAdaptedInterceptors());
  5. String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
  6. for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
  7. if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
  8. chain.addInterceptor(mappedInterceptor.getInterceptor());
  9. }
  10. }
  11. return chain;
  12. }

4、执行拦截器的preHandle方法,如果返回false执行afterCompletion方法并理解返回

5、通过上述获取到了HandlerExecutionChain对象,通过该对象的getHandler()方法获得一个object通过HandlerAdapter进行封装得到HandlerAdapter对象

6、该对象调用handle方法来执行Controller中的方法,该对象如果返回一个ModelAndView给DispatcherServlet

7、DispatcherServlet借助ViewResolver完成逻辑试图名到真实视图对象的解析,得到View后DispatcherServlet使用这个View对ModelAndView中的模型数据进行视图渲染

本文转自:http://blog.csdn.net/liyantianmin/article/details/46948963

源码深度解析SpringMvc请求运行机制(转)的更多相关文章

  1. SpringMVC 源码深度解析&lt;context:component-scan&gt;(扫描和注冊的注解Bean)

    我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比較经经常使用XML配置.控制层依赖的service比較经经常使用注解等(在部署时比較不会改变的) ...

  2. Spring源码深度解析之Spring MVC

    Spring源码深度解析之Spring MVC Spring框架提供了构建Web应用程序的全功能MVC模块.通过策略接口,Spring框架是高度可配置的,而且支持多种视图技术,例如JavaServer ...

  3. mybatis 3.x源码深度解析与最佳实践(最完整原创)

    mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...

  4. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  5. spring源码深度解析— IOC 之 容器的基本实现

    概述 上一篇我们搭建完Spring源码阅读环境,spring源码深度解析—Spring的整体架构和环境搭建 这篇我们开始真正的阅读Spring的源码,分析spring的源码之前我们先来简单回顾下spr ...

  6. Go netpoll I/O 多路复用构建原生网络模型之源码深度解析

    导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go 的I/O 多路复用 netpoll),提供了 goroutine-per- ...

  7. Spring源码深度解析之事务

    Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...

  8. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  9. VueRouter 源码深度解析

    VueRouter 源码深度解析 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还 ...

随机推荐

  1. 国内最快的jquery cdn

    cdnjs.cn是cdnjs.com在国内的镜像服务,项目托管与著名的又拍云存储,目前又拍云在全国有几十个cdn节点,并且还在增加中. cdnjs.cn 托管的jquery相信会成为国内最快的jque ...

  2. 在FreeBSD上搭建Mac的文件及time machine备份服务

    上周将工作用电脑由公司配备的台式机切换到自己低配的macbook air上面,小本本的128G SSD远远不能满足工作的储存需要,但又不舍得入手昂贵的AirPort Time Capsule,于是考虑 ...

  3. 使用HTML5中的element.dataset操作自定义data-*数据

    不久之前我向大家展示了非常有用的classList API,它是一种HTML5里提供的原生的对页面元素的CSS类进行增.删改的接口,完全可以替代jQuery里的那些CSS类操作方法.而另外一个非常有用 ...

  4. 【BZOJ】【3210】花神的浇花集会

    曼哈顿距离与切比雪夫距离 QAQ蒟蒻并不知道切比雪夫距离是什么……并不会做这道题…… 去膜拜了PoPoQQQ大爷的题解: 题目大意:给定平面上的n个点,求一个点到这n个点的切比雪夫距离之和最小 与31 ...

  5. draw call 的优化

    用一张贴图,renderstate都设置成一致,多个draw合并成一个

  6. mysql死锁,等待资源,事务锁,Lock wait timeout exceeded; try restarting transaction解决

    前面已经了解了InnoDB关于在出现锁等待的时候,会根据参数innodb_lock_wait_timeout的配置,判断是否需要进行timeout的操作,本文档介绍在出现锁等待时候的查看及分析处理: ...

  7. Sqli-labs less 29

    Less-29 首先先看下tomcat中的index.jsp文件 在apache的index.php中,sql语句为 $sql="SELECT * FROM users WHERE id=' ...

  8. Sqli-labs less 65

    Less-65 $id = '"'.$id.'"'; // Querry DB to get the correct output $sql="SELECT * FROM ...

  9. python 安装 管理包 pip

    2.7的坑里出不来了,现在已经换到3.4了,不存在下列问题. win7下安装pip    http://blog.chinaunix.net/uid-24984661-id-4202194.html ...

  10. DevExpress licenses.licx 问题

    在DevExpress ( 当然并不范指DevExpress,很多收费软件都是这样的)中,licenses.licx 是用户许可证书文件,当我们使用某些ActiveX(是Microsoft对于一系列策 ...