前一小节我们分析了SpringMVC容器的启动,DispatcherServlet的初始化,HandleMapping,HandleAdaptor,主题,视图解析器等组件的准备工作,现在可以开始接收请求了。我们一般不提倡覆盖Servlet的service方法,除非有特殊的需要。springMVC就覆盖了这个方法,我们来看下SpringMVC都做了什么操作

protected void org.springframework.web.servlet.FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        //如果请求方法是patch的时候走processRequest,其他情况还是走的servlet
        //的默认实现
		if (HttpMethod.PATCH.matches(request.getMethod())) {
			processRequest(request, response);
		}
		else {
			super.service(request, response);
		}
	}

但是你点开doGet,doPost等方法,基本上都是调用的processRequest方法,那就很奇怪了,为什么要像上面那样写代码,那是因为默认的servlet实现没有patch请求方法,所以这里做了特殊处理。

好了,我们直接看到processRequest方法

protected final void org.springframework.web.servlet.FrameworkServlet.processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		long startTime = System.currentTimeMillis();
		Throwable failureCause = null;
        //从当前线程中获取LocaleContext,也就是locale国际化使用的,LocaleContextHolder内部持有两个ThreadLocal,其中
        //有一个是继承父线程值的InheritableLocale
		LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
		//使用locale解析器从request中解析出locale,然后封装成LocaleContext
		LocaleContext localeContext = buildLocaleContext(request);
        //又是从ThreadLocal中获取资源,RequestAttributes可以存储属性-》值键值对,也可以获取对应key的值
		RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
		//构建ServletRequestAttributes,持有request,可以存属性值到tomcat的request中,也可以存在tomcat的session中
		ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
        //创建异步处理器,用于支持servlet3提供的异步请求
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
		//添加回调拦截器,用于在异步调用处理逻辑的时候绑定localeContext, requestAttributes
		asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
        //初始化上下文,其实就是将 localeContext, requestAttributes绑定到当前请求线程中
		initContextHolders(request, localeContext, requestAttributes);

		try {
		    //处理服务
			doService(request, response);
		}
		catch (ServletException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (IOException ex) {
			failureCause = ex;
			throw ex;
		}
		catch (Throwable ex) {
			failureCause = ex;
			throw new NestedServletException("Request processing failed", ex);
		}

		finally {
		    //恢复旧的值
			resetContextHolders(request, previousLocaleContext, previousAttributes);
			if (requestAttributes != null) {
			    //调用请求销毁回调,更新session信息,并标记请求结束
				requestAttributes.requestCompleted();
			}

			if (logger.isDebugEnabled()) {
				if (failureCause != null) {
					this.logger.debug("Could not complete request", failureCause);
				}
				else {
					if (asyncManager.isConcurrentHandlingStarted()) {
						logger.debug("Leaving response open for concurrent processing");
					}
					else {
						this.logger.debug("Successfully completed request");
					}
				}
			}
            //触发请求处理事件
			publishRequestHandledEvent(request, response, startTime, failureCause);
		}
	}

doService

protected void org.springframework.web.servlet.DispatcherServlet.doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        。。。。。。
		// Keep a snapshot of the request attributes in case of an include,
		// to be able to restore the original attributes after the include.
		Map<String, Object> attributesSnapshot = null;
		//保存快照,以便修改好可以恢复
		if (WebUtils.isIncludeRequest(request)) {
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
					attributesSnapshot.put(attrName, request.getAttribute(attrName));
				}
			}
		}

		// Make framework objects available to handlers and view objects.
		//DispatcherServlet.class.getName() + ".CONTEXT" -> WebApplicationContext
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
		//DispatcherServlet.class.getName() + ".LOCALE_RESOLVER" -> this.localeResolver
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
		//DispatcherServlet.class.getName() + ".THEME_RESOLVER" -> this.themeResolver
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
		//DispatcherServlet.class.getName() + ".THEME_SOURCE" -> getThemeSource()
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
        
        //获取上次保存的FlashMap和更新FlashMap,去除过期的FlashMap
        //(*1*)
		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		
		if (inputFlashMap != null) {
		
		    //DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP" -》 inputFlashMap
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		
		//DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP" -》 new FlashMap()
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		
		//DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER" -》  this.flashMapManager
		request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

		try {
		    //分发请求
			doDispatch(request, response);
		}
		finally {
		    //异步请求是否仍在进行中或者已经结束或者还未开始
			if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
				// Restore the original attribute snapshot, in case of an include.
				if (attributesSnapshot != null) {
				    //恢复快照属性值
					restoreAttributesAfterInclude(request, attributesSnapshot);
				}
			}
		}
	}
	
	//(*1*)
	public final FlashMap org.springframework.web.servlet.support.AbstractFlashMapManager.retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {
	    //从session中获取属性为SessionFlashMapManager.class.getName() + ".FLASH_MAPS"的值
	    //这是所有的FlashMap,FlashMap一个继承了HashMap的类
		List<FlashMap> allFlashMaps = retrieveFlashMaps(request);
		if (CollectionUtils.isEmpty(allFlashMaps)) {
			return null;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Retrieved FlashMap(s): " + allFlashMaps);
		}
		//获取过期的FlashMap
		List<FlashMap> mapsToRemove = getExpiredFlashMaps(allFlashMaps);
		//获取匹配的FlashMap,匹配规则:请求路径一样,FlashMap中期望的参数名是实际request的请求参数的子集
		//FlashMap中期望的参数值也是实际request的请求参数值的子集
		//对所有符合要求的进行排序,参数长的优先
		FlashMap match = getMatchingFlashMap(allFlashMaps, request);
		if (match != null) {
		    //加入到移除集合中,因为这个匹配到FlashMap会在此次请求中使用
			mapsToRemove.add(match);
		}
        
		if (!mapsToRemove.isEmpty()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Removing FlashMap(s): " + mapsToRemove);
			}
			//获取互斥锁,一般是从session获取,属性值为WebUtils.class.getName() + ".MUTEX",如果没有设置
			//那么直接返回session作为互斥锁
			Object mutex = getFlashMapsMutex(request);
			if (mutex != null) {
			    //同步,一般对于同一个session,也就是同一个用户其实很少出现这种并发的情况
			    //当然这也是有可能的,比如异步请求,可能请求的延时,就有可能发生竞争
				synchronized (mutex) {
				    //从session中重新获取,可能已经发生了更新
					allFlashMaps = retrieveFlashMaps(request);
					if (allFlashMaps != null) {
					    //移除
						allFlashMaps.removeAll(mapsToRemove);
						//更新到request中
						updateFlashMaps(allFlashMaps, request, response);
					}
				}
			}
			else {
			    //移除
				allFlashMaps.removeAll(mapsToRemove);
				//更新到request
				updateFlashMaps(allFlashMaps, request, response);
			}
		}

		return match;
	}

doDispatch

protected void org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;
        //获取异步管理器
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
			    //检查这个请求是否是上传请求,如果是,那么包装这个Request
			    //spring提供了两种方式,如果是servlet3以上的,将使用servlet的part进行文件流的封装
			    //如果不是将使用Apache提供的文件处理组件处理
				processedRequest = checkMultipart(request);
				//如果对象发生了变化,那么说明当前请求被解析成了multipartRequest
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				//获取mappedHandler
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
				    //打印No mapping found,可以配置为抛出错误,默认是直接返回404
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				//寻找能够处理当前handler的适配器
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				//判断是否过期,如果没有过去,设置response为304
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}
                //调用拦截器的preHandle方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				//通过适配器处理handler
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                //异步请求是否已经结束
				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
                //如果没有设置视图(可能是字符串类型的视图名,也有可能是具体的View对象)
				applyDefaultViewName(processedRequest, mv);
				//应用拦截器器的后置处理
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			//处理分发结果
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
		    //调用全局异常处理,如果有必要还会渲染错误信息视图,最后调用拦截器的afterCompletion方法
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Error err) {
		    //调用全局异常处理,如果有必要还会渲染错误信息视图,最后调用拦截器的afterCompletion方法
			triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
		}
		finally {
		    //如果异步处理还在处理
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				//从拦截器中寻找AsyncHandlerInterceptor,并调用其afterConcurrentHandlingStarted方法
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				//如果是上传请求,清理文件(清理内存,或者文件比较大的话还会存在临时文件)
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

从请求转发的代码中,我们可以看到,spring处理请求总体上分为这几部:

  • 通过HandleMapping寻找handler
  • 如果没有找到,打印日志,然后就是报错或者报404(可在web.xml中配置)
  • 寻找能够处理handler的adapter
  • 是否是get或者head请求,对比缓存时间,如果没有过期直接返回304
  • 调用拦截器前置处理
  • adapter处理handler
  • 处理默认视图名,比如返回void,默认的命名转换器会将request的uri进行转换,去除前后的/,去除扩展名
  • 调用拦截器后置处理
  • 如果有错误并且不是ModelAndViewDefiningException,调用全局异常处理器
  • 解析视图,渲染视图
  • 调用拦截器的complete处理
  • 如果是异步处理,还会调用同步后置处理
  • 如果是上传请求,会清理上传资源

下面我们大致看下获取handler的逻辑

protected HandlerExecutionChain org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest request) throws Exception {
        //循环所有的HandlerMapping,如果有一个找打handler并停止继续向下执行
		for (HandlerMapping hm : this.handlerMappings) {
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

获取HandlerExecutionChain,HandlerExecutionChain是一个驱动类,用于驱动链条执行的驱动器

public class HandlerExecutionChain {
    //日志
	private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
    //handler对象
	private final Object handler;
    //拦截器数组
	private HandlerInterceptor[] interceptors;
    //拦截器集合
	private List<HandlerInterceptor> interceptorList;
    //当前执行到的下标位置,如果某个拦截器发生拦截(下标还是指向的还是上一个拦截器),那么triggerAfterCompletion方法将从这个下标开始
    //向前执行
	private int interceptorIndex = -1;
	
	。。。。。。
}

HandlerExecutionChain.applyPreHandle

boolean org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
			for (int i = 0; i < interceptors.length; i++) {
				HandlerInterceptor interceptor = interceptors[i];
				if (!interceptor.preHandle(request, response, this.handler)) {
				    //如果被拦截立马执行当前拦截器的triggerAfterCompletion方法,
				    //从前一个拦截器的下标开始从后往前执行
					triggerAfterCompletion(request, response, null);
					return false;
				}
				//记录执行到下标
				this.interceptorIndex = i;
			}
		}
		return true;
	}

HandlerExecutionChain.applyPostHandle

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
		    //从后往前执行
			for (int i = interceptors.length - 1; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				interceptor.postHandle(request, response, this.handler, mv);
			}
		}
	}

HandlerExecutionChain.triggerAfterCompletion

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {

		HandlerInterceptor[] interceptors = getInterceptors();
		if (!ObjectUtils.isEmpty(interceptors)) {
		    //从之前记录的拦截器位置,向前执行
			for (int i = this.interceptorIndex; i >= 0; i--) {
				HandlerInterceptor interceptor = interceptors[i];
				try {
					interceptor.afterCompletion(request, response, this.handler, ex);
				}
				catch (Throwable ex2) {
					logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
				}
			}
		}
	}

接下来将进入HandlerMapping的学习