DispatcherServlet源码流程分析

版权声明:本文为博主原创文章,转载请附上链接。 https://blog.csdn.net/qq_36182135/article/details/84934633

DispatcherServlet是Spring MVC的核心内容,理解它的具体服务流程对于中高级应用开发是不可缺少的,下面将通过对源码进行注释来分析下DispatcherServlet的流程处理

  • doService

作为分发请求的方法,doService方法的作用和servlet中的doService作用类似,接收http请求,然后提供对应的服务

	/**
	 * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
	 * for the actual dispatching.
	 */
	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isDebugEnabled()) {
			String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
			logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
					" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
		}

        //快照处理,使用快照可以更快响应用户请求
		// 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.
        //web IOC容器设置
		request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
        //国际化属性设置
		request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        //主体属性设置
		request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        //一样是主题设置
		request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
        //FlashMap开发部分
		FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
		if (inputFlashMap != null) {
			request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
		}
		request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
		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);
				}
			}
		}
	}

这个方法中,做了对快照的处理和部分属性的设置,重要的是所跳转到的doDispatch方法

  • doDispatch

	protected void 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 {
                //设置文件上传处理解析器,并对是否为文件上传请求进行分析
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

                //获得匹配的执行器,如果执行器为空,进行错误处理
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

                //找到对应的执行器-->HandlerAdapter
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                //开始处理请求头,即对GET或POST请求进行处理
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
                //GET处理
				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;
					}
				}
                //执行拦截器前的方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				//执行处理器,返回ModelAndView
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}
                //设置视图名称
				applyDefaultViewName(processedRequest, mv);
                //执行拦截器后的方法
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
            //对请求结果做解析,如果是逻辑视图,则解析名称,否则不解析,最后渲染视图
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}

        //都是对异常的处理方法
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Error err) {
			triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
		}
        //释放资源
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}

Dispatch方法的主要流程是:

  1. 通过请求找到对应的处理链,包括拦截器和控制器
  2. 通过处理器找到对应的适配器
  3. 执行拦截器的事前方法,如果返回false,则流程结束
  4. 通过适配器运行处理器,返回模型和视图
  5. 对视图和模型进行处理,执行拦截器事后方法
  6. 进行视图和模型的解析操作
  • getHandler

在Dispatch方法中,用到了处理器和拦截器,这也是Dispatch方法的核心,接下来就是获得处理器的方法getHandler

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //遍历HandlerMapping
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
            //将获得的HandlerMapping对象进行转换HandlerExecutionChain对象
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

HandlerMapping是SpringMVC启动时初始化的处理器映射,这里做的操作主要是转换成HandlerExecutionChain对象,也就是拦截器链,成员属性如下

public class HandlerExecutionChain {

	private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);

    //控制器对象
	private final Object handler;
    //拦截器数组
	private HandlerInterceptor[] interceptors;
    //拦截器链表
	private List<HandlerInterceptor> interceptorList;
    //拦截器下标,在对拦截器进行注册时起定位作用
	private int interceptorIndex = -1;
......
}

在这个对象里用到的成员属性都是使用HandlerInterceptor声明的,点进HandlerInterceptor,可以看到有一段对HandlerInterceptor的介绍

 * <p>HandlerInterceptor is basically similar to a Servlet Filter, but in
 * contrast to the latter it just allows custom pre-processing with the option
 * of prohibiting the execution of the handler itself, and custom post-processing.
 * Filters are more powerful, for example they allow for exchanging the request
 * and response objects that are handed down the chain. Note that a filter
 * gets configured in web.xml, a HandlerInterceptor in the application context.

翻译过来就是:HandlerInterceptor基本上类似于Servlet过滤器,但与后者不同的是,它允许自定义预处理和自定义后处理,比过滤器更强大,例如,它们允许在链式处理中传递equest和response请求,过滤器是在web.xml中配置的,而拦截器是在application中定义的

这里的自定义预处理和后处理也就是刚才在Dispatch方法中标注出来的操作

HandlerInterceptor有三个方法

public interface HandlerInterceptor {

	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
	    throws Exception;

	void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;

	
	void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception;

}

分别对应拦截器处理前,处理时,处理后所用到的方法,这就是处理器handler中拦截器的内容

dispatch方法的流程中最后是对视图进行解析,源码里就是processDispatchResult方法对视图路径进行解析,对视图类型进行判断,比较简单,就不粘出来了

猜你喜欢

转载自blog.csdn.net/qq_36182135/article/details/84934633