zoukankan      html  css  js  c++  java
  • 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;
    	}
  • 相关阅读:
    记一次HTTP劫持故障排查
    前面任意字符+固定字符+任意字符+固定字符匹配
    php-fpm启动,重启,终止操作
    crontab防止脚本周期内未执行完重复执行
    js深拷贝和浅拷贝
    vue 异步刷新页面,
    vue强制刷新组件
    js判断终端以及APP应用判断
    微信返回上一页的按钮会强制性使用页面缓存,不刷新页面
    json键和值转数组
  • 原文地址:https://www.cnblogs.com/cplinux/p/15364772.html
Copyright © 2011-2022 走看看