• SpringBoot启动中,DispatcherServlet即SpringMvc的加载流程


    前言

    前面我们分析到SpringBoot在启动的过程中,执行到AbstractApplicationContext的refresh方法时,执行到了onRefresh() 过程的时候,开始创建WebServer,在此过程中,加载类tomcat服务器和一些特殊类型的Bean:Servlet、Filter等,在其中我们发现了一个我们熟悉的Servlet,DispatcherServlet,并在此找到了它的启动入口,接下来我们详细分析一下DispatcherServlet的加载过程。前言中介绍到的加载过程,可以查看博客SpringBoot启动过程的“onRefresh() 在特定的上下文子类中初始化其他特殊bean 主题对象和创建webServer”章节。

    DispatcherServlet 注册阶段

    ServletWebServerApplicationContext.createWebServer

    在调用selfInitialize自我初始化函数的时候,遍历调用加载的Bean的onStartup方法,并且传入ServletContext上下文;

    public class ServletWebServerApplicationContext extends GenericWebApplicationContext
    		implements ConfigurableWebServerApplicationContext {
    	private void createWebServer() {
    		WebServer webServer = this.webServer;
    		ServletContext servletContext = getServletContext();
    		if (webServer == null && servletContext == null) {
    			StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
    			//从BeanFactory获取factory 实例对象
    			ServletWebServerFactory factory = getWebServerFactory();
    			createWebServer.tag("factory", factory.getClass().toString());
    			this.webServer = factory.getWebServer(getSelfInitializer());
    			createWebServer.end();
    			getBeanFactory().registerSingleton("webServerGracefulShutdown",
    					new WebServerGracefulShutdownLifecycle(this.webServer));
    			getBeanFactory().registerSingleton("webServerStartStop",
    					new WebServerStartStopLifecycle(this, this.webServer));
    		}
    		else if (servletContext != null) {
    			try {
    				getSelfInitializer().onStartup(servletContext);
    			}
    			catch (ServletException ex) {
    				throw new ApplicationContextException("Cannot initialize servlet context", ex);
    			}
    		}
    		initPropertySources();
    	}
    
    	//自我初始化函数
    	private void selfInitialize(ServletContext servletContext) throws ServletException {
    		//此处的servletContext是在创建tomcat服务器的时候,创建的,在回调时传入该变量
    		prepareWebApplicationContext(servletContext);
    		//注册一个应用范围域的作用域,在工厂和servletContext中注册该作用域
    		registerApplicationScope(servletContext);
    		//将servletContext注册为bean对象
    		WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
    		//获取servlet上下文初始化Bean,并调用对应Bean的startup方法,触发servletContext启动事件
    		for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
    			beans.onStartup(servletContext);
    		}
    	}
    
    
    	//注册一个应用范围域的作用域,在工厂和servletContext中注册该作用域
    	private void registerApplicationScope(ServletContext servletContext) {
    		ServletContextScope appScope = new ServletContextScope(servletContext);
    		getBeanFactory().registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
    		// Register as ServletContext attribute, for ContextCleanupListener to detect it.
    		servletContext.setAttribute(ServletContextScope.class.getName(), appScope);
    	}
    
    	//构建了一个ServletContextInitializerBeans实例对象
    	protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
    		return new ServletContextInitializerBeans(getBeanFactory());
    	}
    }
    
    

    RegistrationBean.onStartUp

    调用ServletRegistrationBean的getDescription获取描述符,然后调用注册方法

    public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
    	private int order = Ordered.LOWEST_PRECEDENCE;
    	@Override
    	public final void onStartup(ServletContext servletContext) throws ServletException {
    		//description = servlet dispatcherServlet
    		String description = getDescription();
    		if (!isEnabled()) {
    			logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
    			return;
    		}
    		register(description, servletContext);
    	}
    
    }
    
    

    ServletRegistrationBean

    调用 getDescription获取描述符

    public class ServletRegistrationBean<T extends Servlet> extends DynamicRegistrationBean<ServletRegistration.Dynamic> {
    	@Override
    	protected String getDescription() {
    		Assert.notNull(this.servlet, "Servlet must not be null");
    		return "servlet " + getServletName();
    	}
    }
    

    DispatcherServlet初始化阶段,初始化的源头

    DispatcherServlet的初始化阶段是在请求request的时候触发的,此处可以根据调用栈倒推一下,servlet使用的策略对象是在initStrategies方法中生成的。而initStrategies方法的调用是onRefresh方法,此处的onRefresh的调用又是根据发布事件触发的

    DispatcherServlet

    public class DispatcherServlet extends FrameworkServlet {
    	@Override
    	protected void onRefresh(ApplicationContext context) {
    		initStrategies(context);
    	}
    	/**
    	 * 初始化这个servlet使用的策略对象
    	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
    	 */
    	protected void initStrategies(ApplicationContext context) {
    		initMultipartResolver(context);
    		initLocaleResolver(context);
    		initThemeResolver(context);
    		initHandlerMappings(context);
    		initHandlerAdapters(context);
    		initHandlerExceptionResolvers(context);
    		initRequestToViewNameTranslator(context);
    		initViewResolvers(context);
    		initFlashMapManager(context);
    	}
    }
    

    此处用到了策略模式

    FrameworkServlet

    此处我们跟踪到onRefresh方法是由onApplicationEvent方法触发的,而onApplicationEvent方法是由ContextRefreshListener 上下文刷新监听器监听到的。而ContextRefreshListener 的生成是在FrameworkServlet 的configureAndRefreshWebApplicationContext方法中,而configureAndRefreshWebApplicationContext又是在createWebApplicationContext方法中调用的;而createWebApplicationContext又是在
    initWebApplicationContext方法中调用的;而initWebApplicationContext方法又是在initServletBean方法中调用的;而initServletBean又是在HttpServletBean的initServletBean方法的实现方法,initServletBean方法是在HttpServletBean的init方法中调用的

    public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    	//初始化Servlet Bean
    	protected final void initServletBean() throws ServletException {
    		getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
    		if (logger.isInfoEnabled()) {
    			logger.info("Initializing Servlet '" + getServletName() + "'");
    		}
    		long startTime = System.currentTimeMillis();
    
    		try {
    			this.webApplicationContext = initWebApplicationContext();
    			initFrameworkServlet();
    		}
    		catch (ServletException | RuntimeException ex) {
    			logger.error("Context initialization failed", ex);
    			throw ex;
    		}
    
    		if (logger.isDebugEnabled()) {
    			String value = this.enableLoggingRequestDetails ?
    					"shown which may lead to unsafe logging of potentially sensitive data" :
    					"masked to prevent unsafe logging of potentially sensitive data";
    			logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
    					"': request parameters and headers will be " + value);
    		}
    
    		if (logger.isInfoEnabled()) {
    			logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
    		}
    	}
    	//初始化web应用上下文 初始化并发布这个servlet的WebApplicationContext。
    	protected WebApplicationContext initWebApplicationContext() {
    		WebApplicationContext rootContext =
    				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
    		WebApplicationContext wac = null;
    
    		if (this.webApplicationContext != null) {
    			// A context instance was injected at construction time -> use it
    			wac = this.webApplicationContext;
    			if (wac instanceof ConfigurableWebApplicationContext) {
    				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
    				if (!cwac.isActive()) {
    					// The context has not yet been refreshed -> provide services such as
    					// setting the parent context, setting the application context id, etc
    					if (cwac.getParent() == null) {
    						// The context instance was injected without an explicit parent -> set
    						// the root application context (if any; may be null) as the parent
    						cwac.setParent(rootContext);
    					}
    					configureAndRefreshWebApplicationContext(cwac);
    				}
    			}
    		}
    		if (wac == null) {
    			// No context instance was injected at construction time -> see if one
    			// has been registered in the servlet context. If one exists, it is assumed
    			// that the parent context (if any) has already been set and that the
    			// user has performed any initialization such as setting the context id
    			wac = findWebApplicationContext();
    		}
    		if (wac == null) {
    			// No context instance is defined for this servlet -> create a local one
    			wac = createWebApplicationContext(rootContext);
    		}
    
    		if (!this.refreshEventReceived) {
    			// Either the context is not a ConfigurableApplicationContext with refresh
    			// support or the context injected at construction time had already been
    			// refreshed -> trigger initial onRefresh manually here.
    			synchronized (this.onRefreshMonitor) {
    				onRefresh(wac);
    			}
    		}
    
    		if (this.publishContext) {
    			// Publish the context as a servlet context attribute.
    			String attrName = getServletContextAttributeName();
    			getServletContext().setAttribute(attrName, wac);
    		}
    
    		return wac;
    	}
    
    	//创建web应用上下文
    	protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
    		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");
    		}
    		ConfigurableWebApplicationContext wac =
    				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
    
    		wac.setEnvironment(getEnvironment());
    		wac.setParent(parent);
    		String configLocation = getContextConfigLocation();
    		if (configLocation != null) {
    			wac.setConfigLocation(configLocation);
    		}
    		configureAndRefreshWebApplicationContext(wac);
    
    		return wac;
    	}
    	//配置和刷新web应用上下文
    	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
    			// The application context id is still set to its original default value
    			// -> assign a more useful id based on available information
    			if (this.contextId != null) {
    				wac.setId(this.contextId);
    			}
    			else {
    				// Generate default id...
    				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()));
    
    		// The wac environment's #initPropertySources will be called in any case when the context
    		// is refreshed; do it eagerly here to ensure servlet property sources are in place for
    		// use in any post-processing or initialization that occurs below prior to #refresh
    		ConfigurableEnvironment env = wac.getEnvironment();
    		if (env instanceof ConfigurableWebEnvironment) {
    			((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
    		}
    
    		postProcessWebApplicationContext(wac);
    		applyInitializers(wac);
    		wac.refresh();
    	}
    
    	private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
    
    		@Override
    		public void onApplicationEvent(ContextRefreshedEvent event) {
    			FrameworkServlet.this.onApplicationEvent(event);
    		}
    	}
    
    	// 从这个servlet的WebApplicationContext接收刷新事件的回调。
    	public void onApplicationEvent(ContextRefreshedEvent event) {
    		this.refreshEventReceived = true;
    		synchronized (this.onRefreshMonitor) {
    			onRefresh(event.getApplicationContext());
    		}
    	}
    
    
    }
    

    HttpServletBean

    而HttpServletBean 的init方法的调用是由GenericServlet 的init方法触发的

    public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
    	// 将配置参数映射到这个servlet的bean属性上,并调用子类初始化。
    	public final void init() throws ServletException {
    
    		// 从初始化参数中设置bean属性。
    		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) {
    				if (logger.isErrorEnabled()) {
    					logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
    				}
    				throw ex;
    			}
    		}
    
    		// 让子类做任何他们喜欢的初始化。
    		initServletBean();
    	}
    }
    

    GenericServlet

    GenericServlet即子类DispatcherServlet的init(ServletConfig config) 方法是由StandardWrapper 的initServlet方法调用的。

    public abstract class GenericServlet implements Servlet, ServletConfig,
            java.io.Serializable {
        public void init(ServletConfig config) throws ServletException {
            this.config = config;
            this.init();
        }
        // 一个方便的方法,它可以被重写,这样就不需要调用<code>super.init(config)</code>。
        public void init() throws ServletException {
            // NOOP by default
        }
    }
    

    StandardWrapper

    initServlet(Servlet servlet)方法调用了servlet.init(facade)方法,此处的servlet即DispatcherServlet;而initServlet(Servlet servlet)方法又是在StandardWrapper 的allocate方法调用的;而allocate方法是在StandardWrapperValve的invoke方法中调用的

    // <b>Wrapper</b>接口的标准实现,它表示一个单独的servlet定义。不允许子容器存在,父容器必须是上下文。
    public class StandardWrapper extends ContainerBase
        implements ServletConfig, Wrapper, NotificationEmitter {
    
        /**
        *分配一个这个Servlet的初始化实例,该实例已经准备好调用它的<code>service()</code>方法。
        *如果servlet类没有实现<code>SingleThreadModel</code>,则(唯一的)初始化实例可能会立即返回。
        *如果servlet类实现了<code>SingleThreadModel</code>,则包装器的实现必须确保在调用<code>deallocate()</code>
        *释放该实例之前不会再次分配该实例。
        */
        public Servlet allocate() throws ServletException {
    
           
            boolean newInstance = false;
    
            // If not SingleThreadedModel, return the same instance every time
            if (!singleThreadModel) {
                // Load and initialize our instance if necessary
                if (instance == null || !instanceInitialized) {
                    synchronized (this) {
                        if (instance == null) {
                            try {
                            
                               
                                // 此处加载已经注册的servlet,即DispatcherServlet
                                instance = loadServlet();
                                newInstance = true;
                             
                        if (!instanceInitialized) {
                            initServlet(instance);
                        }
                    }
                }
    
                if (singleThreadModel) {
                    if (newInstance) {
                        // Have to do this outside of the sync above to prevent a
                        // possible deadlock
                        synchronized (instancePool) {
                            instancePool.push(instance);
                            nInstances++;
                        }
                    }
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("  Returning non-STM instance");
                    }
                    // For new instances, count will have been incremented at the
                    // time of creation
                    if (!newInstance) {
                        countAllocated.incrementAndGet();
                    }
                    return instance;
                }
            }
    
            synchronized (instancePool) {
                while (countAllocated.get() >= nInstances) {
                    // Allocate a new instance if possible, or else wait
                    if (nInstances < maxInstances) {
                        try {
                            instancePool.push(loadServlet());
                            nInstances++;
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            ExceptionUtils.handleThrowable(e);
                            throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                        }
                    } else {
                        try {
                            instancePool.wait();
                        } catch (InterruptedException e) {
                            // Ignore
                        }
                    }
                }
                if (log.isTraceEnabled()) {
                    log.trace("  Returning allocated STM instance");
                }
                countAllocated.incrementAndGet();
                return instancePool.pop();
            }
        }
    
        private synchronized void initServlet(Servlet servlet)
                throws ServletException {
    
            if (instanceInitialized && !singleThreadModel) {
                return;
            }
    
            // Call the initialization method of this servlet
            try {
                if( Globals.IS_SECURITY_ENABLED) {
                    boolean success = false;
                    try {
                        Object[] args = new Object[] { facade };
                        SecurityUtil.doAsPrivilege("init",
                                                   servlet,
                                                   classType,
                                                   args);
                        success = true;
                    } finally {
                        if (!success) {
                            // destroy() will not be called, thus clear the reference now
                            SecurityUtil.remove(servlet);
                        }
                    }
                } else {
                    servlet.init(facade);
                }
    
                instanceInitialized = true;
            } catch (Throwable f) {
    
                throw new ServletException
                    (sm.getString("standardWrapper.initException", getName()), f);
            }
        }
    
    

    StandardWrapperValve

    分析到这里我们可以大概知道DispatcherServlet其实是由request的请求,导致调用Servlet的init方法,对DispatcherServlet进行初始化操作的,再往下分析便是tomcat的细节了,我们在别处进行讨论。
    我们在此看一下invoke方法中,都有哪些动作:调用完wrapper.allocate方法,对Servlet即DispatcherServlet初始化完毕后,调用了ApplicationFilterFactory.createFilterChain方法,创建了filterChain 过滤器链:

    OrderedCharacterEncodingFilter
    OrderedFormContentFilter
    OrderedRequestContextFilter
    WsFilter
    

    加载完filter之后,执行filterChain.doFilter方法对filter和serlvet进行调用

    final class StandardWrapperValve extends ValveBase {
    
        public final void invoke(Request request, Response response)
            throws IOException, ServletException {
    
    
            long t1=System.currentTimeMillis();
            requestCount.incrementAndGet();
            StandardWrapper wrapper = (StandardWrapper) getContainer();
            Servlet servlet = null;
            Context context = (Context) wrapper.getParent();
    
            // Check for the application being marked unavailable
            if (!context.getState().isAvailable()) {
                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                               sm.getString("standardContext.isUnavailable"));
                unavailable = true;
            }
    
           。。。。。。
    
            // Allocate a servlet instance to process this request 分配一个servlet实例来处理这个请求
            try {
                if (!unavailable) {
                    servlet = wrapper.allocate();
                }
            } catch (UnavailableException e) {
               
                long available = wrapper.getAvailable();
                if ((available > 0L) && (available < Long.MAX_VALUE)) {
                   
                } else if (available == Long.MAX_VALUE) {
                  
                }
            } catch (ServletException e) {
                
            } catch (Throwable e) {
               
            }
    
            MessageBytes requestPathMB = request.getRequestPathMB();
            DispatcherType dispatcherType = DispatcherType.REQUEST;
            if (request.getDispatcherType()==DispatcherType.ASYNC) {
                dispatcherType = DispatcherType.ASYNC;
            }
            request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
            request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
                    requestPathMB);
            // Create the filter chain for this request
            ApplicationFilterChain filterChain =
                    ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    
            // Call the filter chain for this request 调用此请求的过滤器链
            // NOTE: This also calls the servlet's service() method 这也调用servlet的service()方法
            Container container = this.container;
            try {
                if ((servlet != null) && (filterChain != null)) {
                    // Swallow output if needed 如果需要,吞咽输出
                    if (context.getSwallowOutput()) {
                        try {
                            SystemLogHandler.startCapture();
                            if (request.isAsyncDispatching()) {
                                request.getAsyncContextInternal().doInternalDispatch();
                            } else {
                                filterChain.doFilter(request.getRequest(),
                                        response.getResponse());
                            }
                        } finally {
                            String log = SystemLogHandler.stopCapture();
                            if (log != null && log.length() > 0) {
                                context.getLogger().info(log);
                            }
                        }
                    } else {
                        
                    }
    
                }
            } catch (ClientAbortException | CloseNowException e) {
                exception(request, response, e);
            } catch (IOException e) {
               
                exception(request, response, e);
            } catch (UnavailableException e) {
                container.getLogger().error(sm.getString(
                        "standardWrapper.serviceException", wrapper.getName(),
                        context.getName()), e);
                //            throwable = e;
                //            exception(request, response, e);
                wrapper.unavailable(e);
                long available = wrapper.getAvailable();
                if ((available > 0L) && (available < Long.MAX_VALUE)) {
                    response.setDateHeader("Retry-After", available);
                    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
                               sm.getString("standardWrapper.isUnavailable",
                                            wrapper.getName()));
                } else if (available == Long.MAX_VALUE) {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND,
                                sm.getString("standardWrapper.notFound",
                                            wrapper.getName()));
                }
               
            } catch (ServletException e) {   
            } finally {
                // Release the filter chain (if any) for this request
                if (filterChain != null) {
                    filterChain.release();
                }
    
                // Deallocate the allocated servlet instance 释放分配的servlet实例
                try {
                    if (servlet != null) {
                        wrapper.deallocate(servlet);
                    }
                } catch (Throwable e) {
                  
                }
            }
        }
    
    }
    
    ApplicationFilterChain

    调用doFilter方法,内部调用internalDoFilter方法即内部DoFilter方法,内部DoFilter方法调用对应Filter的doFilter方法,此处先调用了doFilter的父类OncePerRequestFilter方法,当filte执行完毕之后,执行servlet的service方法,即HttpServlet的service方法。service方法内部根据request请求方式调用servlet对应的方法,此处的get方法请求FrameworkServlet的doGet方法,该方法内部调用processRequest方法,此处我们继续看DispatcherServlet处理请求阶段

    public final class ApplicationFilterChain implements FilterChain {
        private static final ThreadLocal<ServletRequest> lastServicedRequest;
        private static final ThreadLocal<ServletResponse> lastServicedResponse;
        private int pos = 0;
        private int n = 0;
        private Servlet servlet = null;
        static {
            if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                lastServicedRequest = new ThreadLocal<>();
                lastServicedResponse = new ThreadLocal<>();
            } else {
                lastServicedRequest = null;
                lastServicedResponse = null;
            }
        }
        private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    
        public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
    
            if( Globals.IS_SECURITY_ENABLED ) {
                final ServletRequest req = request;
                final ServletResponse res = response;
                try {
                    java.security.AccessController.doPrivileged(
                            (java.security.PrivilegedExceptionAction<Void>) () -> {
                                internalDoFilter(req,res);
                                return null;
                            }
                    );
                } catch( PrivilegedActionException pe) {
                   
                }
            } else {
                internalDoFilter(request,response);
            }
        }
    
        private void internalDoFilter(ServletRequest request,
                                      ServletResponse response)
            throws IOException, ServletException {
    
            // Call the next filter if there is one
            if (pos < n) {
                ApplicationFilterConfig filterConfig = filters[pos++];
                try {
                    // 从config中获取当前要调用的filter
                    Filter filter = filterConfig.getFilter();
    
                    if (request.isAsyncSupported() && "false".equalsIgnoreCase(
                            filterConfig.getFilterDef().getAsyncSupported())) {
                        request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
                    }
                    if( Globals.IS_SECURITY_ENABLED ) {
                        final ServletRequest req = request;
                        final ServletResponse res = response;
                        Principal principal =
                            ((HttpServletRequest) req).getUserPrincipal();
    
                        Object[] args = new Object[]{req, res, this};
                        SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
                    } else {
                        // 调用对应filter的doFilter方法
                        filter.doFilter(request, response, this);
                    }
                } catch (IOException | ServletException | RuntimeException e) {
                    throw e;
                } catch (Throwable e) {
                   
                }
                return;
            }
    
            // We fell off the end of the chain -- call the servlet instance
            try {
                if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                    lastServicedRequest.set(request);
                    lastServicedResponse.set(response);
                }
    
                if (request.isAsyncSupported() && !servletSupportsAsync) {
                    request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
                            Boolean.FALSE);
                }
                // Use potentially wrapped request from this point
                if ((request instanceof HttpServletRequest) &&
                        (response instanceof HttpServletResponse) &&
                        Globals.IS_SECURITY_ENABLED ) {
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal =
                        ((HttpServletRequest) req).getUserPrincipal();
                    Object[] args = new Object[]{req, res};
                    SecurityUtil.doAsPrivilege("service",
                                               servlet,
                                               classTypeUsedInService,
                                               args,
                                               principal);
                } else {
                    servlet.service(request, response);
                }
            } catch (IOException | ServletException | RuntimeException e) {
                throw e;
            } finally {
                if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
                    lastServicedRequest.set(null);
                    lastServicedResponse.set(null);
                }
            }
        }
    
    }
    
    OncePerRequestFilter
    /**
    *这个{@code doFilter}实现存储了一个用于"already filtered"的请求属性,
    *如果该属性已经存在,则不进行再次过滤。
    */
    public abstract class OncePerRequestFilter extends GenericFilterBean {
    	public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
    
    	public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
    			throws ServletException, IOException {
    
    		if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
    			throw new ServletException("OncePerRequestFilter just supports HTTP requests");
    		}
    		HttpServletRequest httpRequest = (HttpServletRequest) request;
    		HttpServletResponse httpResponse = (HttpServletResponse) response;
    
    		String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
    		boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
    
    		if (skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {
    
    			// Proceed without invoking this filter...
    			filterChain.doFilter(request, response);
    		}
    		else if (hasAlreadyFilteredAttribute) {
    
    			if (DispatcherType.ERROR.equals(request.getDispatcherType())) {
    				doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain);
    				return;
    			}
    
    			// Proceed without invoking this filter...
    			filterChain.doFilter(request, response);
    		}
    		else {
    			// Do invoke this filter...
    			request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
    			try {
    				doFilterInternal(httpRequest, httpResponse, filterChain);
    			}
    			finally {
    				// Remove the "already filtered" request attribute for this request.
    				request.removeAttribute(alreadyFilteredAttributeName);
    			}
    		}
    	}
    }
    

    DispatcherServlet 初始化组件阶段

    DispatcherServlet

    随着调用的请求过程,初始化过程中

    public class DispatcherServlet extends FrameworkServlet {
    
    	@Override
    	protected void onRefresh(ApplicationContext context) {
    		initStrategies(context);
    	}
    	// 初始化这个servlet使用的策略对象。
    	protected void initStrategies(ApplicationContext context) {
    		// 处理文件上传的策略组件对象
    		initMultipartResolver(context);
    		// 初始化该类使用的区域设置解析器。
    		initLocaleResolver(context);
    		// 初始化该类使用的主题解析器
    		initThemeResolver(context);
    		// 初始化这个类使用的处理器映射。
    		initHandlerMappings(context);
    		// 初始化该类使用的处理程序适配器
    		initHandlerAdapters(context);
    		// 初始化该类使用的处理程序异常解析器。
    		initHandlerExceptionResolvers(context);
    		// 初始化这个servlet实例使用的请求查看名称转换器
    		initRequestToViewNameTranslator(context);
    		// 初始化这个类使用的视图解析器。
    		initViewResolvers(context);
    		// 初始化这个servlet实例使用的Flash Map Manager。
    		initFlashMapManager(context);
    	}
    
    }
    
    	// 为DispatcherServlet的成员变量 multipartResolver 赋值,从上下文获取
    	private void initMultipartResolver(ApplicationContext context) {
    		try {
    			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
    		}
    		
    	}
    
    	private void initLocaleResolver(ApplicationContext context) {
    		try {
    			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
    	}
    
    	private void initThemeResolver(ApplicationContext context) {
    		try {
    			this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);	
    		}
    		
    	}
    

    initHandlerMappings

    此处获取到的matchingBeans 有:

    "requestMappingHandlerMapping" -> {RequestMappingHandlerMapping@6627} 
    "welcomePageHandlerMapping" -> {WelcomePageHandlerMapping@8127} 
    "beanNameHandlerMapping" -> {BeanNameUrlHandlerMapping@8129} 
    "routerFunctionMapping" -> {RouterFunctionMapping@6611} 
    "resourceHandlerMapping" -> {SimpleUrlHandlerMapping@8131} 
    
    
    public class DispatcherServlet extends FrameworkServlet {
    
    	private List<HandlerMapping> handlerMappings;
    	private void initHandlerMappings(ApplicationContext context) {
    		this.handlerMappings = null;
    
    		if (this.detectAllHandlerMappings) {
    			// 找到ApplicationContext中的所有HandlerMappings,包括祖先上下文。
    			Map<String, HandlerMapping> matchingBeans =
    					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    			if (!matchingBeans.isEmpty()) {
    				this.handlerMappings = new ArrayList<>(matchingBeans.values());
    				// We keep HandlerMappings in sorted order.
    				AnnotationAwareOrderComparator.sort(this.handlerMappings);
    			}
    		}
    		else {
    			
    		}
    
    		// Ensure we have at least one HandlerMapping, by registering
    		// a default HandlerMapping if no other mappings are found.
    		if (this.handlerMappings == null) {
    			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
    		}
    
    		for (HandlerMapping mapping : this.handlerMappings) {
    			if (mapping.usesPathPatterns()) {
    				this.parseRequestPath = true;
    				break;
    			}
    		}
    	}
    }
    

    RequestMappingHandlerMapping

    /**
    *在{@link Controller @Controller}类中从类型级和方法级{@link RequestMapping @RequestMapping}注释中
    *创建{@link RequestMappingInfo}实例。
    */
    public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
    		implements MatchableHandlerMapping, EmbeddedValueResolverAware {
    
    }
    

    BeanNameUrlHandlerMapping

    /**
    *实现{@link org.springframework.web.servlet。HandlerMapping}接口,
    *它将url映射到名称以斜杠("/")开头的bean,类似于Struts将url映射到动作名的方式
    */
    public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping {
    	// 检查以“/”开头的给定bean的名称和别名的url。
    	@Override
    	protected String[] determineUrlsForHandler(String beanName) {
    		List<String> urls = new ArrayList<>();
    		if (beanName.startsWith("/")) {
    			urls.add(beanName);
    		}
    		String[] aliases = obtainApplicationContext().getAliases(beanName);
    		for (String alias : aliases) {
    			if (alias.startsWith("/")) {
    				urls.add(alias);
    			}
    		}
    		return StringUtils.toStringArray(urls);
    	}
    }
    

    initHandlerAdapters

    "requestMappingHandlerAdapter" -> {RequestMappingHandlerAdapter@6634} 
    "handlerFunctionAdapter" -> {HandlerFunctionAdapter@6625} 
    "httpRequestHandlerAdapter" -> {HttpRequestHandlerAdapter@8296} 
    "simpleControllerHandlerAdapter" -> {SimpleControllerHandlerAdapter@8298}
    
    public class DispatcherServlet extends FrameworkServlet {
    	private void initHandlerAdapters(ApplicationContext context) {
    		this.handlerAdapters = null;
    
    		if (this.detectAllHandlerAdapters) {
    			// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
    			Map<String, HandlerAdapter> matchingBeans =
    					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
    			if (!matchingBeans.isEmpty()) {
    				this.handlerAdapters = new ArrayList<>(matchingBeans.values());
    				// We keep HandlerAdapters in sorted order.
    				AnnotationAwareOrderComparator.sort(this.handlerAdapters);
    			}
    		}
    		else {
    			try {
    				HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
    				this.handlerAdapters = Collections.singletonList(ha);
    			}
    			
    		}
    
    		// Ensure we have at least some HandlerAdapters, by registering
    		// default HandlerAdapters if no other adapters are found.
    		if (this.handlerAdapters == null) {
    			this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
    		}
    	}
    
    
    }
    

    RequestMappingHandlerAdapter

    
    /**
    *{@link AbstractHandlerMethodAdapter}的扩展,它支持{@link @RequestMapping}注释的{@link HandlerMethods}。
    */
    public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
    		implements BeanFactoryAware, InitializingBean {
    
    }
    

    initHandlerExceptionResolvers

    "errorAttributes" -> {DefaultErrorAttributes@8351} 
    "handlerExceptionResolver" -> {HandlerExceptionResolverComposite@8353} 
    
    public class DispatcherServlet extends FrameworkServlet {
    
    	private RequestToViewNameTranslator viewNameTranslator;
    	private void initHandlerExceptionResolvers(ApplicationContext context) {
    		this.handlerExceptionResolvers = null;
    		if (this.detectAllHandlerExceptionResolvers) {
    			// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
    			Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
    					.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
    			if (!matchingBeans.isEmpty()) {
    				this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());
    				// We keep HandlerExceptionResolvers in sorted order.
    				AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
    			}
    		}
    		else {
    			try {
    				HandlerExceptionResolver her =
    						context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
    				this.handlerExceptionResolvers = Collections.singletonList(her);
    			}
    			
    		}
    
    		// Ensure we have at least some HandlerExceptionResolvers, by registering
    		// default HandlerExceptionResolvers if no other resolvers are found.
    		if (this.handlerExceptionResolvers == null) {
    			this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
    			
    		}
    	}
    }
    

    initRequestToViewNameTranslator

    public class DispatcherServlet extends FrameworkServlet {
    	private RequestToViewNameTranslator viewNameTranslator;
    	private void initRequestToViewNameTranslator(ApplicationContext context) {
    		try {
    			this.viewNameTranslator =
    					context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    		
    		}
    	}
    }
    

    initViewResolvers

    加载到的视图解析器有

    "beanNameViewResolver" -> {BeanNameViewResolver@6507} 
    "mvcViewResolver" -> {ViewResolverComposite@8438} 
    "defaultViewResolver" -> {InternalResourceViewResolver@6609} 
    "viewResolver" -> {ContentNegotiatingViewResolver@6511} 
    
    
    public class DispatcherServlet extends FrameworkServlet {
    	private void initViewResolvers(ApplicationContext context) {
    		this.viewResolvers = null;
    
    		if (this.detectAllViewResolvers) {
    			// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
    			Map<String, ViewResolver> matchingBeans =
    					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
    			if (!matchingBeans.isEmpty()) {
    				this.viewResolvers = new ArrayList<>(matchingBeans.values());
    				// We keep ViewResolvers in sorted order.
    				AnnotationAwareOrderComparator.sort(this.viewResolvers);
    			}
    		}
    		else {
    			try {
    				ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
    				this.viewResolvers = Collections.singletonList(vr);
    			}
    			catch (NoSuchBeanDefinitionException ex) {
    				// Ignore, we'll add a default ViewResolver later.
    			}
    		}
    
    		// Ensure we have at least one ViewResolver, by registering
    		// a default ViewResolver if no other resolvers are found.
    		if (this.viewResolvers == null) {
    			this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
    		}
    	}
    }
    
    

    initFlashMapManager

    public class DispatcherServlet extends FrameworkServlet {
    	private FlashMapManager flashMapManager;
    	private void initFlashMapManager(ApplicationContext context) {
    		try {
    			this.flashMapManager = context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			
    		}
    	}
    
    

    FrameworkServlet

    执行完onRefresh方法,返回到FrameworkServlet的initServletBean方法,继续执行

    DispatcherServlet处理请求阶段

    FrameworkServlet

    public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
    	// 处理此请求,不管结果如何发布事件,实际的事件处理是由抽象的{@link #doService}模板方法执行的。
    	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 (ServletException | IOException ex) {
    			failureCause = ex;
    			throw ex;
    		}
    		catch (Throwable ex) {
    			failureCause = ex;
    			throw new NestedServletException("Request processing failed", ex);
    		}
    
    		finally {
    			resetContextHolders(request, previousLocaleContext, previousAttributes);
    			if (requestAttributes != null) {
    				requestAttributes.requestCompleted();
    			}
    			logResult(request, response, failureCause, asyncManager);
    			publishRequestHandledEvent(request, response, startTime, failureCause);
    		}
    	}
    
    	/**
    	*子类必须实现这个方法来完成请求处理工作,接收GET、POST、PUT和DELETE的集中回调。
    	*这个契约本质上与HttpServlet中常用的{@code doGet}或{@code doPost}方法的契约是一样的。
    	*这个类拦截调用,以确保异常处理和事件发布发生。
    	*/
    	protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
    			throws Exception;
    }
    

    DispatcherServlet

    在调用doDispatch的过程中,在执行ha.handle方法执行之前,首先调用了mappedHandler.applyPreHandle方法,执行了拦截器的前置处理方法;
    在执行完ha.handle方法之后,调用了mappedHandler.applyPostHandle方法对结果进行后置处理

    public class DispatcherServlet extends FrameworkServlet {
    
    	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		logRequest(request);
    
    		// 保留请求属性的快照,以防出现包含,以便能够在包含之后恢复原始属性。
    		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);
    		}
    
    		RequestPath previousRequestPath = null;
    		if (this.parseRequestPath) {
    			previousRequestPath = (RequestPath) request.getAttribute(ServletRequestPathUtils.PATH_ATTRIBUTE);
    			ServletRequestPathUtils.parseAndCache(request);
    		}
    
    		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);
    				}
    			}
    			if (this.parseRequestPath) {
    				ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
    			}
    		}
    
    
    	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    		if (this.handlerAdapters != null) {
    			// this.handlerAdapters:
    			// 0 = {RequestMappingHandlerAdapter@6739} 
    			// 1 = {HandlerFunctionAdapter@6740} 
    			// 2 = {HttpRequestHandlerAdapter@6741} 
    			// 3 = {SimpleControllerHandlerAdapter@6742} 
    			for (HandlerAdapter adapter : this.handlerAdapters) {
    				if (adapter.supports(handler)) {
    					return adapter;
    				}
    			}
    		}
    		throw new ServletException("No adapter for handler [" + handler +
    				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    	}
    	}
    
    
    	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) {
    					noHandlerFound(processedRequest, response);
    					return;
    				}
    
    				// 确定当前请求的处理程序适配器 
    				// 此处ha = RequestMappingHandlerAdapter实例对象
    				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    				// Process last-modified header, if supported by the handler.
    				String method = request.getMethod();
    				boolean isGet = HttpMethod.GET.matches(method);
    				if (isGet || HttpMethod.HEAD.matches(method)) {
    					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
    					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
    						return;
    					}
    				}
    				// 首先执行拦截器链的preHandle方法
    				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    					return;
    				}
    
    				// Actually invoke the handler. 实际调用处理程序
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
    				if (asyncManager.isConcurrentHandlingStarted()) {
    					return;
    				}
    
    				applyDefaultViewName(processedRequest, mv);
    				mappedHandler.applyPostHandle(processedRequest, response, mv);
    			}
    			catch (Exception ex) {
    				
    			}
    			catch (Throwable err) {
    				
    			}
    			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    		}
    		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);
    				}
    			}
    		}
    	}
    
    	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;
    	}
    }
    

    AbstractHandlerMapping.getHandler

    public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
    		implements HandlerMapping, Ordered, BeanNameAware {
    
    	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    		//得到处理方法,并封装了bean对象
    		Object handler = getHandlerInternal(request);
    		if (handler == null) {
    			handler = getDefaultHandler();
    		}
    		if (handler == null) {
    			return null;
    		}
    		// Bean name or resolved handler?
    		if (handler instanceof String) {
    			String handlerName = (String) handler;
    			handler = obtainApplicationContext().getBean(handlerName);
    		}
    
    		// Ensure presence of cached lookupPath for interceptors and others
    		if (!ServletRequestPathUtils.hasCachedPath(request)) {
    			initLookupPath(request);
    		}
    		// 返回执行器链,包括处理器本身和拦截器链
    		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    
    		if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
    			CorsConfiguration config = getCorsConfiguration(handler, request);
    			if (getCorsConfigurationSource() != null) {
    				CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
    				config = (globalConfig != null ? globalConfig.combine(config) : config);
    			}
    			if (config != null) {
    				config.validateAllowCredentials();
    			}
    			executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
    		}
    
    		// 返回执行器链,包括处理器本身和拦截器链
    		return executionChain;
    	}
    	// 初始化用于请求映射的路径。此处进入 else逻辑
    	protected String initLookupPath(HttpServletRequest request) {
    		if (usesPathPatterns()) {
    			request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE);
    			RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request);
    			String lookupPath = requestPath.pathWithinApplication().value();
    			return UrlPathHelper.defaultInstance.removeSemicolonContent(lookupPath);
    		}
    		else {
    			return getUrlPathHelper().resolveAndCacheLookupPath(request);
    		}
    	}
    
    	// 获取处理执行器链
    	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
    				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    
    		for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
    			if (interceptor instanceof MappedInterceptor) {
    				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
    				if (mappedInterceptor.matches(request)) {
    					chain.addInterceptor(mappedInterceptor.getInterceptor());
    				}
    			}
    			else {
    				chain.addInterceptor(interceptor);
    			}
    		}
    		return chain;
    	}
    }
    

    RequestMappingInfoHandlerMapping.getHandlerInternal

    public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> {
    	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    		request.removeAttribute(PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
    		try {
    			return super.getHandlerInternal(request);
    		}
    		finally {
    			ProducesRequestCondition.clearMediaTypesAttribute(request);
    		}
    	}
    }
    

    AbstractHandlerMethodMapping

    public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
    	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    		String lookupPath = initLookupPath(request);
    		this.mappingRegistry.acquireReadLock();
    		try {
    			// 从映射注册中心获取处理方法
    			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
    			// 根据bean名称,为handlerMethod 填充bean属性
    			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    		}
    		finally {
    			this.mappingRegistry.releaseReadLock();
    		}
    	}
    
    	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    		List<Match> matches = new ArrayList<>();
    		// T = RequestMappingInfo
    		List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
    
    		if (directPathMatches != null) {
    			addMatchingMappings(directPathMatches, matches, request);
    		}
    		if (matches.isEmpty()) {
    			addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
    		}
    		if (!matches.isEmpty()) {
    			Match bestMatch = matches.get(0);
    			if (matches.size() > 1) {
    				Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
    				matches.sort(comparator);
    				bestMatch = matches.get(0);
    				if (logger.isTraceEnabled()) {
    					logger.trace(matches.size() + " matching mappings: " + matches);
    				}
    				if (CorsUtils.isPreFlightRequest(request)) {
    					for (Match match : matches) {
    						if (match.hasCorsConfig()) {
    							return PREFLIGHT_AMBIGUOUS_MATCH;
    						}
    					}
    				}
    				else {
    					Match secondBestMatch = matches.get(1);
    					if (comparator.compare(bestMatch, secondBestMatch) == 0) {
    						Method m1 = bestMatch.getHandlerMethod().getMethod();
    						Method m2 = secondBestMatch.getHandlerMethod().getMethod();
    						String uri = request.getRequestURI();
    						throw new IllegalStateException(
    								"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
    					}
    				}
    			}
    			request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.getHandlerMethod());
    			handleMatch(bestMatch.mapping, lookupPath, request);
    			return bestMatch.getHandlerMethod();
    		}
    		else {
    			return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
    		}
    	}
    	// 添加映射
    	private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
    		for (T mapping : mappings) {
    			T match = getMatchingMapping(mapping, request);
    			if (match != null) {
    				matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
    			}
    		}
    	}
    
    	class MappingRegistry {
    		// 返回匹配给定URL路径。不是线程安全的。
    		public List<T> getMappingsByDirectPath(String urlPath) {
    			return this.pathLookup.get(urlPath);
    		}
    	}
    }
    
    public class UrlPathHelper {
    	// 返回web应用程序中给定请求的路径。
    	public String getPathWithinApplication(HttpServletRequest request) {
    		String contextPath = getContextPath(request);
    		String requestUri = getRequestUri(request);
    		String path = getRemainingPath(requestUri, contextPath, true);
    		if (path != null) {
    			// Normal case: URI contains context path.
    			return (StringUtils.hasText(path) ? path : "/");
    		}
    		else {
    			return requestUri;
    		}
    	}
    }
    

    HandlerAdapter.handle

    public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    			throws Exception {
    
    		return handleInternal(request, response, (HandlerMethod) handler);
    	}
    
    }
    

    RequestMappingHandlerAdapter

    public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
    		implements BeanFactoryAware, InitializingBean {
    	
    	protected ModelAndView handleInternal(HttpServletRequest request,
    			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
    		ModelAndView mav;
    		checkRequest(request);
    
    		// 如果需要,在同步块中执行invokeHandlerMethod。此处进入else逻辑
    		if (this.synchronizeOnSession) {
    			HttpSession session = request.getSession(false);
    			if (session != null) {
    				Object mutex = WebUtils.getSessionMutex(session);
    				synchronized (mutex) {
    					mav = invokeHandlerMethod(request, response, handlerMethod);
    				}
    			}
    			else {
    				// No HttpSession available -> no mutex necessary
    				mav = invokeHandlerMethod(request, response, handlerMethod);
    			}
    		}
    		else {
    			// No synchronization on session demanded at all...
    			mav = invokeHandlerMethod(request, response, handlerMethod);
    		}
    
    		if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
    			if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
    				applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
    			}
    			else {
    				prepareResponse(response);
    			}
    		}
    
    		return mav;
    	}
    
    	// 调用处理器
    	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
    			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
    		// 构建web请求,包含request 和 response
    		ServletWebRequest webRequest = new ServletWebRequest(request, response);
    		try {
    			// 根据方法和转换服务生成一个ServletRequestDataBinderFactory对象
    			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
    			// 根据给出的@ModelAttribute方法,创建一个实例对象
    			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
    
    			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
    			if (this.argumentResolvers != null) {
    				// 设置一个参数解析器
    				invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
    			}
    			if (this.returnValueHandlers != null) {
    				invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
    			}
    			// 设置数据绑定工厂
    			invocableMethod.setDataBinderFactory(binderFactory);
    			// 设置参数名称发现器
    			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
    			// 定义一个实体视图容器
    			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
    			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
    			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
    			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
    
    			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
    			asyncWebRequest.setTimeout(this.asyncRequestTimeout);
    
    			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    			asyncManager.setTaskExecutor(this.taskExecutor);
    			asyncManager.setAsyncWebRequest(asyncWebRequest);
    			asyncManager.registerCallableInterceptors(this.callableInterceptors);
    			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
    
    			if (asyncManager.hasConcurrentResult()) {
    				Object result = asyncManager.getConcurrentResult();
    				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
    				asyncManager.clearConcurrentResult();
    				LogFormatUtils.traceDebug(logger, traceOn -> {
    					String formatted = LogFormatUtils.formatValue(result, !traceOn);
    					return "Resume with async result [" + formatted + "]";
    				});
    				invocableMethod = invocableMethod.wrapConcurrentResult(result);
    			}
    			// 调用方法
    			invocableMethod.invokeAndHandle(webRequest, mavContainer);
    			if (asyncManager.isConcurrentHandlingStarted()) {
    				return null;
    			}
    
    			return getModelAndView(mavContainer, modelFactory, webRequest);
    		}
    		finally {
    			webRequest.requestCompleted();
    		}
    	}
    	// 根据给定的HandlerMethod定义创建一个Servlet可调用HandlerMethod。
    	protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
    		return new ServletInvocableHandlerMethod(handlerMethod);
    	}
    }
    

    HandlerMethod

    public class HandlerMethod {
    	protected HandlerMethod(HandlerMethod handlerMethod) {
    		Assert.notNull(handlerMethod, "HandlerMethod is required");
    		this.bean = handlerMethod.bean;
    		this.beanFactory = handlerMethod.beanFactory;
    		this.messageSource = handlerMethod.messageSource;
    		this.beanType = handlerMethod.beanType;
    		this.method = handlerMethod.method;
    		this.bridgedMethod = handlerMethod.bridgedMethod;
    		this.parameters = handlerMethod.parameters;
    		this.responseStatus = handlerMethod.responseStatus;
    		this.responseStatusReason = handlerMethod.responseStatusReason;
    		this.description = handlerMethod.description;
    		this.resolvedFromHandlerMethod = handlerMethod.resolvedFromHandlerMethod;
    	}
    }
    

    InvocableHandlerMethod

    invokeForRequest方法首先调用getMethodArgumentValues方法获取方法参数值,获取到参数之后,调用doInvoke方法,进行处理

    public class InvocableHandlerMethod extends HandlerMethod {
    	private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
    
    	private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    	public InvocableHandlerMethod(HandlerMethod handlerMethod) {
    		super(handlerMethod);
    	}
    
    	public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
    			Object... providedArgs) throws Exception {
    
    		Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    		if (logger.isTraceEnabled()) {
    			logger.trace("Arguments: " + Arrays.toString(args));
    		}
    		return doInvoke(args);
    	}
    
    	protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
    			Object... providedArgs) throws Exception {
    
    		MethodParameter[] parameters = getMethodParameters();
    		if (ObjectUtils.isEmpty(parameters)) {
    			return EMPTY_ARGS;
    		}
    
    		Object[] args = new Object[parameters.length];
    		// 对参数进行解析
    		for (int i = 0; i < parameters.length; i++) {
    			MethodParameter parameter = parameters[i];
    			parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
    			args[i] = findProvidedArgument(parameter, providedArgs);
    			if (args[i] != null) {
    				continue;
    			}
    			if (!this.resolvers.supportsParameter(parameter)) {
    				throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
    			}
    			try {
    				args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
    			}
    			catch (Exception ex) {
    				// Leave stack trace for later, exception may actually be resolved and handled...
    				if (logger.isDebugEnabled()) {
    					String exMsg = ex.getMessage();
    					if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
    						logger.debug(formatArgumentError(parameter, exMsg));
    					}
    				}
    				throw ex;
    			}
    		}
    		return args;
    	}
    
    	protected Object doInvoke(Object... args) throws Exception {
    		Method method = getBridgedMethod();
    		try {
    			if (KotlinDetector.isSuspendingFunction(method)) {
    				return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
    			}
    			return method.invoke(getBean(), args);
    		}
    		catch (IllegalArgumentException ex) {
    			
    		}
    		catch (InvocationTargetException ex) {
    			
    		}
    	}
    
    	public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
    		this.resolvers = argumentResolvers;
    	}
    }
    

    ServletInvocableHandlerMethod

    调用invokeAndHandle方法,方法内部首先调用了父类的 invokeForRequest方法,方法返回返回值,随后调用returnValueHandlers的handleReturnValue方法将结果输出。

    public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
    	private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
    	public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {
    		super(handlerMethod);
    	}
    	// 注册HandlerMethod返回值处理程序实例来处理返回值。
    	public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {
    		this.returnValueHandlers = returnValueHandlers;
    	}
    	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
    			Object... providedArgs) throws Exception {
    
    		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    		setResponseStatus(webRequest);
    
    		if (returnValue == null) {
    			if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
    				disableContentCachingIfNecessary(webRequest);
    				mavContainer.setRequestHandled(true);
    				return;
    			}
    		}
    		else if (StringUtils.hasText(getResponseStatusReason())) {
    			mavContainer.setRequestHandled(true);
    			return;
    		}
    
    		mavContainer.setRequestHandled(false);
    		Assert.state(this.returnValueHandlers != null, "No return value handlers");
    		try {
    			this.returnValueHandlers.handleReturnValue(
    					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    		}
    		catch (Exception ex) {
    			if (logger.isTraceEnabled()) {
    				logger.trace(formatErrorForReturnValue(returnValue), ex);
    			}
    			throw ex;
    		}
    	}
    
    }
    
    handleReturnValue

    returnValueHandlers:

    0 = {ModelAndViewMethodReturnValueHandler@9410} 
    1 = {ModelMethodProcessor@9411} 
    2 = {ViewMethodReturnValueHandler@9412} 
    3 = {ResponseBodyEmitterReturnValueHandler@9413} 
    4 = {StreamingResponseBodyReturnValueHandler@9414} 
    5 = {HttpEntityMethodProcessor@9415} 
    6 = {HttpHeadersReturnValueHandler@9416} 
    7 = {CallableMethodReturnValueHandler@9417} 
    8 = {DeferredResultMethodReturnValueHandler@9418} 
    9 = {AsyncTaskMethodReturnValueHandler@9419} 
    10 = {ServletModelAttributeMethodProcessor@9420} 
    11 = {RequestResponseBodyMethodProcessor@8319} 
    12 = {ViewNameMethodReturnValueHandler@9421} 
    13 = {MapMethodProcessor@9422} 
    14 = {ServletModelAttributeMethodProcessor@9423} 
    
    

    调用selectHandler方法返回的结果处理器为:RequestResponseBodyMethodProcessor

    public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
    	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
    			ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    
    		HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    		if (handler == null) {
    			throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    		}
    		handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    	}
    
    	// 此处的returnValueHandlers有15个
    	private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
    		boolean isAsyncValue = isAsyncReturnValue(value, returnType);
    		for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
    			if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
    				continue;
    			}
    			if (handler.supportsReturnType(returnType)) {
    				return handler;
    			}
    		}
    		return null;
    	}
    }
    
    RequestResponseBodyMethodProcessor

    handleReturnValue方法内部调用了writeWithMessageConverters方法,将结果输出

    public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
    	public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
    			ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
    			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
    
    		mavContainer.setRequestHandled(true);
    		ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    		ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
    
    		// Try even with null return value. ResponseBodyAdvice could get involved.
    		writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
    	}
    }
    
    AbstractMessageConverterMethodProcessor

    在writeWithMessageConverters方法中,调用了getAdvice().beforeBodyWrite方法,对输出的结果进行处理,即调用RequestBodyAdvice, ResponseBodyAdvice类的拦截方法

    public abstract class AbstractMessageConverterMethodProcessor extends AbstractMessageConverterMethodArgumentResolver
    		implements HandlerMethodReturnValueHandler {
    
    	protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
    			ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
    			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
    
    		Object body;
    		Class<?> valueType;
    		Type targetType;
    
    		if (value instanceof CharSequence) {
    			body = value.toString();
    			valueType = String.class;
    			targetType = String.class;
    		}
    		else {
    			body = value;
    			valueType = getReturnValueType(body, returnType);
    			targetType = GenericTypeResolver.resolveType(getGenericType(returnType), returnType.getContainingClass());
    		}
    
    		if (isResourceType(value, returnType)) {
    			outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");
    			if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null &&
    					outputMessage.getServletResponse().getStatus() == 200) {
    				Resource resource = (Resource) value;
    				try {
    					List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
    					outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value());
    					body = HttpRange.toResourceRegions(httpRanges, resource);
    					valueType = body.getClass();
    					targetType = RESOURCE_REGION_LIST_TYPE;
    				}
    				catch (IllegalArgumentException ex) {
    					outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());
    					outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
    				}
    			}
    		}
    
    		MediaType selectedMediaType = null;
    		MediaType contentType = outputMessage.getHeaders().getContentType();
    		boolean isContentTypePreset = contentType != null && contentType.isConcrete();
    		if (isContentTypePreset) {
    			
    			selectedMediaType = contentType;
    		}
    		else {
    			HttpServletRequest request = inputMessage.getServletRequest();
    			List<MediaType> acceptableTypes;
    			try {
    				acceptableTypes = getAcceptableMediaTypes(request);
    			}
    			catch (HttpMediaTypeNotAcceptableException ex) {
    				int series = outputMessage.getServletResponse().getStatus() / 100;
    				if (body == null || series == 4 || series == 5) {
    					
    					return;
    				}
    				throw ex;
    			}
    			List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);
    
    			if (body != null && producibleTypes.isEmpty()) {
    				throw new HttpMessageNotWritableException(
    						"No converter found for return value of type: " + valueType);
    			}
    			List<MediaType> mediaTypesToUse = new ArrayList<>();
    			for (MediaType requestedType : acceptableTypes) {
    				for (MediaType producibleType : producibleTypes) {
    					if (requestedType.isCompatibleWith(producibleType)) {
    						mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
    					}
    				}
    			}
    			if (mediaTypesToUse.isEmpty()) {
    				if (body != null) {
    					throw new HttpMediaTypeNotAcceptableException(producibleTypes);
    				}
    				if (logger.isDebugEnabled()) {
    					logger.debug("No match for " + acceptableTypes + ", supported: " + producibleTypes);
    				}
    				return;
    			}
    
    			MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
    
    			for (MediaType mediaType : mediaTypesToUse) {
    				if (mediaType.isConcrete()) {
    					selectedMediaType = mediaType;
    					break;
    				}
    				else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
    					selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
    					break;
    				}
    			}
    
    			if (logger.isDebugEnabled()) {
    				
    			}
    		}
    
    		if (selectedMediaType != null) {
    			selectedMediaType = selectedMediaType.removeQualityValue();
    			for (HttpMessageConverter<?> converter : this.messageConverters) {
    				GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
    						(GenericHttpMessageConverter<?>) converter : null);
    				if (genericConverter != null ?
    						((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :
    						converter.canWrite(valueType, selectedMediaType)) {
    					body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
    							(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
    							inputMessage, outputMessage);
    					if (body != null) {
    						Object theBody = body;
    						LogFormatUtils.traceDebug(logger, traceOn ->
    								"Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");
    						addContentDispositionHeader(inputMessage, outputMessage);
    						if (genericConverter != null) {
    							genericConverter.write(body, targetType, selectedMediaType, outputMessage);
    						}
    						else {
    							((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
    						}
    					}
    					else {
    						if (logger.isDebugEnabled()) {
    							logger.debug("Nothing to write: null body");
    						}
    					}
    					return;
    				}
    			}
    		}
    
    		if (body != null) {
    			Set<MediaType> producibleMediaTypes =
    					(Set<MediaType>) inputMessage.getServletRequest()
    							.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
    
    			if (isContentTypePreset || !CollectionUtils.isEmpty(producibleMediaTypes)) {
    				throw new HttpMessageNotWritableException(
    						"No converter for [" + valueType + "] with preset Content-Type '" + contentType + "'");
    			}
    			throw new HttpMediaTypeNotAcceptableException(getSupportedMediaTypes(body.getClass()));
    		}
    	}
    }
    
  • 相关阅读:
    DirectX9:基础篇 第五章 绘制流水线
    他山之石:可以攻玉
    C89:论内存分配问题
    C89:关键字
    MFC:开头篇 介绍
    DirectX9:先导篇 数学基础
    模仿轮播图效果
    text选中后displa出label内容
    ASP.NET页面之间传递值的几种方式
    jquery-delay(),queue()
  • 原文地址:https://www.cnblogs.com/nangonghui/p/15723687.html
Copyright © 2020-2023  润新知