• SpringMVC 源码解析


    前言

    年初面试时接触到一道面试题,在聊到SpringMVC时提到了SpringMVC的开发者为何要设计父子容器呢,又或者说是父子容器的设计有什么更实际的作用呢?
             首先要理解对于一个web应用,当其部署在web容器上时,容器会为其提供一个全局上下文环境ServletContext,这个上下文环境将为后续的Spring提供宿主环境。

    SpringMVC工作流程

    20180708224853769.png

    DispatcherServlet上下文继承关系

    mvc-context-hierarchy.png

    SpringMVC设计的父子容器

    父子容器配置文件

    --在web.xml中配置,两个重要的xml:applicationContext.xml和SpringMVC-conf.xml
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applictionContext.xml</param-value>
    </context-param>
    <listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
      
    <servlet>
        <servlet-name>dispatcher-servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath*:springMVC-conf.xml</param-value>
        </init-param>
    </servlet>
      
    <servlet-mapping>
      <servlet-name>dispatcher-servlet</servlet-name>
      <url-pattern>/*</url-pattern>
    </servlet-mapping>
    

    父子容器的设计目的

    根据SpringMVC的官方解释,父(根)容器主要包括一些基础脚手架的bean,比如Pool、DataSource、Dao、Service。目的是在不同的Servlet实例之间共享。这些不同的bean可以在子容器中重写。
         而子容器主要包括一些Controller、View等一些web相关的bean。

    DispatcherServlet源码分析

    既然SpringMVC中同时包含Spring容器和SpringMVC容器,那么这两个容器都是在什么时候初始化呢?

    根容器初始化

    首先,根容器是通过ServletContext监听器进行创建,默认的监听器为ContextLoaderListener,当web应用启动时,会调用监听器的contextInitialized方法。
          那么根容器的初始化就从ContextLoaderListener类说起吧,,Spring官方对该类的描述是启动监听器去启动和关闭Spring的root WebApplicationContext(翻译的实在有点蹩脚)。
         phpcode1535985292mZsXwg.gif

    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    	public ContextLoaderListener() {
    	}
    
    	public ContextLoaderListener(WebApplicationContext context) {
    		super(context);
    	}
    
        //===初始化root WebApplicationContext===
    	@Override
    	public void contextInitialized(ServletContextEvent event) {
    		initWebApplicationContext(event.getServletContext());
    	}
    
    	@Override
    	public void contextDestroyed(ServletContextEvent event) {
    		closeWebApplicationContext(event.getServletContext());
    		ContextCleanupListener.cleanupAttributes(event.getServletContext());
    	}
    }
    

    //ContextLoader.java
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    	//初始化Spring容器时如果发现servlet 容器中已存在根Spring容根器则抛出异常,证明rootWebApplicationContext只能有一个。
    	if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
    		throw new IllegalStateException(
    				"Cannot initialize context because there is already a root application context present - " +
    				"check whether you have multiple ContextLoader* definitions in your web.xml!");
    	}
    
    	try {
    		//创建webApplicationContext实例
    		if (this.context == null) {
    		    this.context = createWebApplicationContext(servletContext);
    		}
    		if (this.context instanceof ConfigurableWebApplicationContext) {
    			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
    			if (!cwac.isActive()) {
    				if (cwac.getParent() == null) {
    					ApplicationContext parent = loadParentContext(servletContext);
    					cwac.setParent(parent);
    				}
    				//配置WebApplicationContext
    				configureAndRefreshWebApplicationContext(cwac, servletContext);
    			}
    		}
    		
    		/**
    		   把生成的webApplicationContext设置成root WebApplicationContext。保存在ServletContext上下文中。
    		   下一步初始化MVC ApplicationContext时需要从ServletContext取出根上下文作为其父上下文。
    		**/ 
    		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
    
    		ClassLoader ccl = Thread.currentThread().getContextClassLoader();
    		if (ccl == ContextLoader.class.getClassLoader()) {
    			currentContext = this.context;
    		}
    		else if (ccl != null) {
    			currentContextPerThread.put(ccl, this.context);
    		}
    		
    		return this.context;
    	}
    	catch (RuntimeException | Error ex) {
    		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
    		throw ex;
    	}
    }
    

    以上代码主要完成两个功能:创建实例WebApplicationContext实例、把所创建的WebApplicationContext设置为根上下文,也就是设置成为ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

    MVC容器初始化

    大家知道Servlet生命周期都是从init方法开始,desctory方法结束,由jvm负责垃圾回收。而DispatcherServlet也是一个普通的Servlet,先看一下DispatcherServlet的继承关系图,对整个继承关系有个了解。
    1946613-f6892f5c658de75c.jpg
       既然说起Servlet,那就从Servlet的初始化(init)方法入手

    //HttpServletBean.java
    @Override
    public final void init() throws ServletException {
    
    	PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
    	if (!pvs.isEmpty()) {
    		try {
    			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
    			ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
    			bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
    			initBeanWrapper(bw);
    			bw.setPropertyValues(pvs, true);
    		}
    		catch (BeansException ex) {
    			throw ex;
    		}
    	}
    
    	//交给子类重写
    	initServletBean();
    }
    
    //FrameworkServlet.java
    @Override
    protected final void initServletBean() throws ServletException {
    	try {
    		this.webApplicationContext = initWebApplicationContext();
    		initFrameworkServlet();
    	}
    	catch (ServletException | RuntimeException ex) {
    		throw ex;
    	}
    }
    
    //FrameworkServlet.java
    //初始化MVC容器
    protected WebApplicationContext initWebApplicationContext() {
        //从ServletContext取出根上下文
    	WebApplicationContext rootContext =
    			WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    	WebApplicationContext wac = null;
    
    	if (this.webApplicationContext != null) {
    		wac = this.webApplicationContext;
    		if (wac instanceof ConfigurableWebApplicationContext) {
    			ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
    			if (!cwac.isActive()) {
    				if (cwac.getParent() == null) {
    					cwac.setParent(rootContext);
    				}
    				configureAndRefreshWebApplicationContext(cwac);
    			}
    		}
    	}
    	if (wac == null) {
    		wac = findWebApplicationContext();
    	}
    	
    	//如果还没有webApplicatioinContext,创建webApplicationContext
    	if (wac == null) {
    		wac = createWebApplicationContext(rootContext);
    	}
    
    	//子类自定义对servlet子上下文后续操作,在DispatcherServlet中实现
    	if (!this.refreshEventReceived) {
    		synchronized (this.onRefreshMonitor) {
    			//执行子类扩展方法onRefresh,在DispatcherServlet内初始化所有web相关组件
    			onRefresh(wac);
    		}
    	}
    
    	//发布servlet子上下文到ServletContext
    	if (this.publishContext) {
    		String attrName = getServletContextAttributeName();
    		//将servlet子上下文以org.springframework.web.servlet.FrameworkServlet.CONTEXT. + servletName的属性名称注册到ServletContext中
    		getServletContext().setAttribute(attrName, wac);
    	}
    
    	return wac;
    }
    
    protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
    	return createWebApplicationContext((ApplicationContext) parent);
    }
    
    protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
        //获取WebApplicationContext实现类,此处其实就是XmlWebApplicationContext
    	Class<?> contextClass = getContextClass();
    	if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
    		throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +
    				"': custom WebApplicationContext class [" + contextClass.getName() +
    				"] is not of type ConfigurableWebApplicationContext");
    	}
    	
    	//生成XmlWebApplicationContext实例
    	ConfigurableWebApplicationContext wac =
    			(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    
    	wac.setEnvironment(getEnvironment());
    	//设置根容器为父容器 
    	wac.setParent(parent);
    	String configLocation = getContextConfigLocation();
    	if (configLocation != null) {
    	    //设置配置文件
    		wac.setConfigLocation(configLocation);
    	}
    	
    	//配置webApplicationContext
    	configureAndRefreshWebApplicationContext(wac);
    
    	return wac;
    }
    
    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    	if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
    		if (this.contextId != null) {
    			wac.setId(this.contextId);
    		}
    		else {
    			wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());
    		}
    	}
    
    	wac.setServletContext(getServletContext());
    	wac.setServletConfig(getServletConfig());
    	wac.setNamespace(getNamespace());
    	wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
    
    	ConfigurableEnvironment env = wac.getEnvironment();
    	if (env instanceof ConfigurableWebEnvironment) {
    		((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
    	}
    
    	postProcessWebApplicationContext(wac);
    	applyInitializers(wac);
    	
    	//开始处理bean
    	wac.refresh();
    }
    

    上面的关键代码都在FrameworkServlet类中,有几个关键点:取除根上下文,创建子上下文并设置父上下文,完成刷新,把子上下文发布到ServletContext中。 到这里可以说子容器(子上下文)已经创建完成。 并把其他初始化web组件的相关工作交给onRefresh方法完成,由DispatcherServlet来重写onRefresh方法,这就又回到了我们熟悉的initStrategies方法。

    web组件初始化

    @Override
    protected void onRefresh(ApplicationContext context) {
    	initStrategies(context);
    }
    
    protected void initStrategies(ApplicationContext context) {
    	//文件上传解析器
    	initMultipartResolver(context);
    	
    	//本地化解析器
    	initLocaleResolver(context);
    	
    	//主题解析器
    	initThemeResolver(context);
    	
    	//处理器映射器(url和Controller方法的映射)
    	initHandlerMappings(context);
    	
    	//处理器适配器(实际执行Controller方法)
    	initHandlerAdapters(context);
    	
    	//处理器异常解析器
    	initHandlerExceptionResolvers(context);
    	
    	//RequestToViewName解析器
    	initRequestToViewNameTranslator(context);
    	
    	//视图解析器(视图的匹配和渲染)
    	initViewResolvers(context);
    	
    	//FlashMap管理者
    	initFlashMapManager(context);
    }
    

    这里我们主要关注一下三个重要组件:HandlerMapping、HandlerAdapter、ViewResolver。分析这3个组件之前,我们先看一下我们的springMVC-conf.xml配置文件,mvc的配置文件中,我们配置了两行代码:

    <context:component-scan base-package="com.zhangfei"/>
    <mvc:annotation-driven>
    

    第二行代码主要是添加了默认的HandleMapping,ViewResolver,HandleAdapter。我们看看annotation-driven的源码定义,根据spring自定义schema定义,我们找到如下代码,如图所示:
    QQ截图20190822131726.jpg
    该文件就一行代码:

    http://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
    
    //MVC所有的标签解析器都定义在此
    public class MvcNamespaceHandler extends NamespaceHandlerSupport {
    	@Override
    	public void init() {
    		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
    		registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
    		registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
    		registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
    		registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
    		registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
    		registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
    		registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
    		registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
    		registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
    	}
    }
    

    那么通过分析AnnotationDrivenBeanDefinitionParser类,主要完成以下三大组件的装配工作:
    QQ截图20190822132044.jpg

    初始化处理器映射器

    private void initHandlerMappings(ApplicationContext context) {
    	this.handlerMappings = null;
    
        //这里detectAllHandlerMappings默认值为true,可以通过配置文件设置为false
    	if (this.detectAllHandlerMappings) {
    	    //从上下文(包含父上下文)中查找所有HandlerMapping实现类
    		Map<String, HandlerMapping> matchingBeans =
    				BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    		if (!matchingBeans.isEmpty()) {
    			this.handlerMappings = new ArrayList<>(matchingBeans.values());
    			AnnotationAwareOrderComparator.sort(this.handlerMappings);
    		}
    	}
    	else {
    		try {
    		    //这里只取固定的bean
    			HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
    			this.handlerMappings = Collections.singletonList(hm);
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			
    		}
    	}
    	
    	/***
    	  确保至少有一个HandlerMapping,如果没能找到,注册一个默认的
    	  默认规则在DispatcherServlet.properties中,这里也就是取BeanNameUrlHandlerMapping、RequestMappingHandlerMapping
    	***/
    	if (this.handlerMappings == null) {
    		this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);		
    	}
    }
    

    初始化处理器适配器

    private void initHandlerAdapters(ApplicationContext context) {
    	this.handlerAdapters = null;
    
    	if (this.detectAllHandlerAdapters) {
    	    //从上下文(包括父上下文)中查找所有HandlerAdapter实现类
    		Map<String, HandlerAdapter> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
    		if (!matchingBeans.isEmpty()) {
    			this.handlerAdapters = new ArrayList<>(matchingBeans.values());
    			AnnotationAwareOrderComparator.sort(this.handlerAdapters);
    		}
    	}
    	else {
    		try {
    		    //这里取bean名字为handlerAdapter,类型为HandlerAdapter的处理器适配器
    			HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
    			this.handlerAdapters = Collections.singletonList(ha);
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			
    		}
    	}
    	
    	/**
    	如果没找到,则从默认规则里取出指定的三个实现类:HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter
    	**/
    	if (this.handlerAdapters == null) {
    		this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);		
    	}
    }
    

    初始化试图解析器

    private void initViewResolvers(ApplicationContext context) {
    	this.viewResolvers = null;
    
    	if (this.detectAllViewResolvers) {
    	    //从上下文(包括父上下文)中查找所有ViewResolver实现类
    		Map<String, ViewResolver> matchingBeans =BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
    		if (!matchingBeans.isEmpty()) {
    			this.viewResolvers = new ArrayList<>(matchingBeans.values());
    			AnnotationAwareOrderComparator.sort(this.viewResolvers);
    		}
    	}
    	else {
    		try {
    			ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
    			this.viewResolvers = Collections.singletonList(vr);
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			
    		}
    	}
    	
    	/**
    	如果没找到,则从默认规则里取出指定的实现类:InternalResourceViewResolver
    	**/
    	if (this.viewResolvers == null) {
    		this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);	
    	}
    }
    

    三大组件的初始化最后判断为NULL时都会调用getDefaultStrategies方法,也就是从DispatcherServlet.properties中取出指定默认值。

    protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
    	String key = strategyInterface.getName();
    	String value = defaultStrategies.getProperty(key);
    	if (value != null) {
    		String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
    		List<T> strategies = new ArrayList<>(classNames.length);
    		for (String className : classNames) {
    			try {
    				Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
    				Object strategy = createDefaultStrategy(context, clazz);
    				strategies.add((T) strategy);
    			}
    			catch (ClassNotFoundException ex) {
    				throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className +"] for interface [" + key + "]", ex);
    			}
    			catch (LinkageError err) {
    				throw new BeanInitializationException("Unresolvable class definition for DispatcherServlet's default strategy class [" +className + "] for interface [" + key + "]", err);
    			}
    		}
    		return strategies;
    	}
    	else {
    		return new LinkedList<>();
    	}
    }
    

    DispatcherServlet请求处理过程

    提到请求处理过程,我们再来回顾一下Servlet生命周期,处理请求都放在service方法中处理,那么也从DispatcherServlet的service方法入手。DispatcherServlet继承FrameworkServlet,在FrameworkServlet中重写了service、doGet、doPost、doPut、doDelete方法。

    //FrameworkServlet.java
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException, IOException {
    	HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    	if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
    		processRequest(request, response);
    	}
    	else {
    		super.service(request, response);
    	}
    }
    
    	
    @Override
    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);
    }
    
    	
    @Override
    protected final void doPut(HttpServletRequest request, HttpServletResponse response)
    		throws ServletException, IOException {
    	processRequest(request, response);
    }
    
    	
    @Override
    protected final void doDelete(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());
    	
    	//把新构造的LocaleContext对象和ServletRequestAttributes对象和当前请求线程绑定(后面要解除绑定)
    	initContextHolders(request, localeContext, requestAttributes);
    
    	try {
    	    //抽象方法,交给DispatcherServlet方法实现
    		doService(request, response);
    	}
    	catch (ServletException | IOException ex) {
    		failureCause = ex;
    		throw ex;
    	}
    	catch (Throwable ex) {
    		failureCause = ex;
    		throw new NestedServletException("Request processing failed", ex);
    	}
    
    	finally {
    	    //重置LocaleContext和RequestAttributes对象,也就是解除LocaleContext对象和ServletRequestAttributes对象和当前请求线程的绑定
    		resetContextHolders(request, previousLocaleContext, previousAttributes);
    		if (requestAttributes != null) {
    			requestAttributes.requestCompleted();
    		}
    		//发布ServletRequestHandledEvent事件
    		publishRequestHandledEvent(request, response, startTime, failureCause);
    	}
    }
    
    //DispatcherServlet.java
    @Override
    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对象中填充4个属性
    	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()) {
    			if (attributesSnapshot != null) {
    				restoreAttributesAfterInclude(request, attributesSnapshot);
    			}
    		}
    	}
    }
    
    
    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);
                
                //调用handlerMapping获取handlerChain
    			mappedHandler = getHandler(processedRequest);
    			if (mappedHandler == null) {
    				noHandlerFound(processedRequest, response);
    				return;
    			}
    
                //获取支持该handler解析的HandlerAdapter
    			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    			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;
    			}
    
                //使用HandlerAdapter完成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);
    		}
    		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()) {
    			if (mappedHandler != null) {
    				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
    			}
    		}
    		else {
    			if (multipartRequestParsed) {
    				cleanupMultipart(processedRequest);
    			}
    		}
    	}
    }
    

    DispatcherServlet的doDispatch方法概括起来大致就是以下几点:首先根据当前请求路径找到对应的HandlerMethod,一个HandlerMethod和若干个拦截器构造一个HandlerExecutionChain.通过HandlerExecutionChain得到HandlerAdapter对象通过执行HandlerAdapter的handle方法得到ModelAndView对象,调用ModelAndView解析视图,渲染视图,Response结束。

    参考

    https://juejin.im/post/5cb89dae6fb9a0686b47306d
    https://juejin.im/post/5cbc10b46fb9a0689f4c2c22
    https://www.cnblogs.com/fangjian0423/p/springMVC-dispatcherServlet.html

  • 相关阅读:
    Shell基础
    个人对JavaScript预编译的理解
    文件系统管理
    文件特殊权限
    权限管理ACL权限
    用户和用户组管理
    RPM包管理-yum管理
    oracle11g完全卸载方法
    JVM概述
    复杂查询优质习题
  • 原文地址:https://www.cnblogs.com/sword-successful/p/11394370.html
Copyright © 2020-2023  润新知