Spring MVC笔记(三) -- DispatcherServlet请求处理流程

DispatcherServlet

从doGet、doPost方法入手,在父类FrameworkServlet中

protected final void doGet(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	processRequest(request, response);
}

@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {
	processRequest(request, response);
}

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

	long startTime = System.currentTimeMillis();
	Throwable failureCause = null;

	LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
	LocaleContext localeContext = buildLocaleContext(request);

	RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
	ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
	asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
	//绑定当前线程
	initContextHolders(request, localeContext, requestAttributes);
	try {
		//进一步处理
		doService(request, response);
	}
	catch ...
	finally {
		//恢复线程到原始状态
		resetContextHolders(request, previousLocaleContext, previousAttributes);
		if (requestAttributes != null) {
			requestAttributes.requestCompleted();
		}
		logResult(request, response, failureCause, asyncManager);
		//发布事件通知
		publishRequestHandledEvent(request, response, startTime, failureCause);
	}
}

doGet、doPost方法都是调用processRequest方法,做了一些准备工作,然后交由doService方法进一步处理

DispatcherServlet重写了doService方法

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	...
	Map<String, Object> attributesSnapshot = null;
	if (WebUtils.isIncludeRequest(request)) {
		attributesSnapshot = new HashMap<>();
		Enumeration<?> attrNames = request.getAttributeNames();
		while (attrNames.hasMoreElements()) {
			String attrName = (String) attrNames.nextElement();
			if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
				attributesSnapshot.put(attrName, request.getAttribute(attrName));
			}
		}
	}
	// 设置变量
	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());
	if (this.flashMapManager != null) {
		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);
			}
		}
	}
}

做好准备工作将已经初始化的功能辅助工具变量,如localeResolver、themeResolver等设置到request属性中。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);

			//【标记1】 从handlerMappings获取相应的handler
			mappedHandler = getHandler(processedRequest);
			if (mappedHandler == null) {
				noHandlerFound(processedRequest, response);
				return;
			}
			//【标记2】 从handlerAdapters获取相应的handlerAdapter
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
			// 是否支持last-modified
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}
			//调用拦截器的前置方法
			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}
			// 真正调用handler进行请求的处理
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}
			//如果没返回视图,则使用默认的视图
			applyDefaultViewName(processedRequest, mv);
			//调用拦截器的后置方法
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		catch (Throwable err) {
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
		//【标记3】处理handler返回的结果
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new NestedServletException("Handler processing failed", 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);
			}
		}
	}
}

【标记1】获取handler

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
	}
	return null;
}

getHandler方法主要是从handlerMappings获取相应的handler,然后封装成HandlerExecutionChain返回。

【标记2】 获取HandlerAdapter

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	if (this.handlerAdapters != null) {
		for (HandlerAdapter adapter : this.handlerAdapters) {
			if (adapter.supports(handler)) {
				return adapter;
			}
		}
	}
	throw...
}

getHandlerAdapter方法主要是从handlerAdapters获取相应的adapter返回。

【标记3】 视图渲染

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	Locale locale =
			(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
	response.setLocale(locale);
	View view;
	String viewName = mv.getViewName();
	if (viewName != null) {
		// 【标记4】通过视图名获取View.
		view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
		if (view == null) {
			throw...
		}
	}
	else {
		// 检验是否存在视图
		view = mv.getView();
		if (view == null) {
			throw...
		}
	}
	try {
		if (mv.getStatus() != null) {
			response.setStatus(mv.getStatus().value());
		}
		//【标记5】
		view.render(mv.getModelInternal(), request, response);
	}
	catch...
}

protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
		Locale locale, HttpServletRequest request) throws Exception {
	if (this.viewResolvers != null) {
		for (ViewResolver viewResolver : this.viewResolvers) {
			View view = viewResolver.resolveViewName(viewName, locale);
			if (view != null) {
				return view;
			}
		}
	}
	return null;
}

【标记4】获取View对象,以InternalResourceViewResolver为例,resolveViewName在其父类AbstractCachingViewResolver中

public View resolveViewName(String viewName, Locale locale) throws Exception {
	if (!isCache()) {//没缓存就创建
		return createView(viewName, locale);
	}
	else {
		Object cacheKey = getCacheKey(viewName, locale);
		View view = this.viewAccessCache.get(cacheKey);
		if (view == null) {
			synchronized (this.viewCreationCache) {
				view = this.viewCreationCache.get(cacheKey);
				if (view == null) {
					// 子类进行创建
					view = createView(viewName, locale);
					if (view == null && this.cacheUnresolved) {
						view = UNRESOLVED_VIEW;
					}
					if (view != null) {
						this.viewAccessCache.put(cacheKey, view);
						this.viewCreationCache.put(cacheKey, view);
					}
				}
			}
		}
		return (view != UNRESOLVED_VIEW ? view : null);
	}
}

UrlBasedViewResolver类

protected View createView(String viewName, Locale locale) throws Exception {
	// 检查是否支持该视图
	if (!canHandle(viewName, locale)) {
		return null;
	}
	// 重定向处理
	if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
		String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
		RedirectView view = new RedirectView(redirectUrl,
				isRedirectContextRelative(), isRedirectHttp10Compatible());
		String[] hosts = getRedirectHosts();
		if (hosts != null) {
			view.setHosts(hosts);
		}
		return applyLifecycleMethods(REDIRECT_URL_PREFIX, view);
	}
	// 转发处理
	if (viewName.startsWith(FORWARD_URL_PREFIX)) {
		String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
		InternalResourceView view = new InternalResourceView(forwardUrl);
		return applyLifecycleMethods(FORWARD_URL_PREFIX, view);
	}

	// 回到父类的createView进行调用loadView
	return super.createView(viewName, locale);
}

protected View createView(String viewName, Locale locale) throws Exception {
	return loadView(viewName, locale);
}
protected abstract View loadView(String viewName, Locale locale) throws Exception;

protected View loadView(String viewName, Locale locale) throws Exception {
	//真正创建View
	AbstractUrlBasedView view = buildView(viewName);
	//交由spring管理声明周期
	View result = applyLifecycleMethods(viewName, view);
	return (view.checkResource(locale) ? result : null);
}

真正创建View在buildView方法

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
	Class<?> viewClass = getViewClass();
	//创建
	AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(viewClass);
	//设置前缀、后缀
	view.setUrl(getPrefix() + viewName + getSuffix());
	//类型设置
	String contentType = getContentType();
	if (contentType != null) {
		view.setContentType(contentType);
	}
	...
	return view;
}

【标记5】页面跳转

AbstractView类

public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
		HttpServletResponse response) throws Exception {
	...
	//获取整合一些属性
	Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
	prepareResponse(request, response);
	//处理页面跳转
	renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
InternalResourceView类

protected void renderMergedOutputModel(
		Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

	// 把属性设置到request中
	exposeModelAsRequestAttributes(model, request);
	// Expose helpers as request attributes, if any.
	exposeHelpers(request);
	// 获取路径
	String dispatcherPath = prepareForRendering(request, response);
	//拿到请求派发器
	RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
	if (rd == null) {
		throw...
	}
	if (useInclude(request, response)) {
		response.setContentType(getContentType());
		rd.include(request, response);
	}

	else {
		...
		rd.forward(request, response);
	}
}

总结参考:SpringMVC请求流程详解

猜你喜欢

转载自blog.csdn.net/seasonLai/article/details/82797231