SpringMVC学习 十五 DispatcherServlet的doService方法
一、doService方法解读
在SpringMVC种,如果一个请求被DispatcherServlet拦截,就会进入这个DispatcherServlet的doService方法。
在doService方法中,会把DispatcherServlet初始化时创建的WebApplication等信息绑定到请求中,这样方便后续处理流程中其他组件使用。代码如下:
@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logRequest(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<>();
			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中绑定 webApplication、localeResolver、themeResolver等组件
		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);
				}
			}
		}
	}
二、RequestContextUtils
在Spring与SpringMVC整合之后,
- Spring的根应用上下文(也称根容器)会放在ServletContext中,以一个属性的形式存在。key值为org.springframework.web.context.WebApplicationContext.ROOT
- SpringMVC的应用上下文(也称子容器)会被两个地方引用。一个是DispatcherServlet的父类FrameworkServlet的webApplicationContext属性引用。另外一个就是在ServletContext的属性中也可以引用到,key值的命名规则是
FrameworkServlet.class.getName() + ".CONTEXT."+${servletName}if (this.publishContext) { // 把SpringMVC的应用上下文发布到ServletContext中 String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); }
在SpringMVC有一个工具类RequestContextUtils,这个工具类可以获取到SpringMVC的应用上下文,刚开始是从Request中获取,如果获取不到就用WebApplicationContextUtils工具从ServletContext获取,不过此时获取的是根应用上下文。
代码如下:
	public static WebApplicationContext findWebApplicationContext(
			HttpServletRequest request, @Nullable ServletContext servletContext) {
		WebApplicationContext webApplicationContext = (WebApplicationContext) request.getAttribute(
				DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
		if (webApplicationContext == null) {
			if (servletContext != null) {
				webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
			}
			if (webApplicationContext == null) {
				webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
			}
		}
		return webApplicationContext;
	}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号