一、SpringMVC 请求执行的过程

SpringMVC 是一个基于 Spring 框架的 MVC 框架,它简化了 Web 应用程序的开发。采用了前端控制器模式,请求会首先被一个中央控制器 DispatcherServlet 处理,再由其分发到具体的 Controller 进行处理。其中 SpringMVC 的请求执行过程如下图所示:

springsecurity简述执行流程 spring的执行过程_SpringMVC


执行过程如下:

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器,一并返回给 DispatcherServlet
  4. DispatcherServlet 通过 HandlerAdapter处理器适配器调用处理器
  5. 执行处理器,也就是执行 Controller 中的方法
  6. 处理器执行完成返回ModelAndView
  7. HandlerAdapter将处理器的结果ModelAndView返回给DispatcherServlet
  8. DispatcherServletModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. DispatcherServletView进行渲染视图,即将模型数据填充至视图中
  11. DispatcherServlet 响应用户

从上面是 SpringMVC 的执行过程中可以看出,其中 DispatcherServlet 占据着核心的位置,就像售票处的工作人员一样,当乘客(浏览器发送的请求)来到售票处时,工作人员(DispatcherServlet)会根据乘客所需要的目的地(请求的处理器)来为他们发放对应的门票(响应结果),下面我们从 DispatcherServlet 入手开始分析 SpringMVC 的源码。

二、SpringMVC 请求执行的过程源码解析

2.1 初始化操作

其中 DispatcherServletorg.springframework.web.servlet 包下,可以看到该类继承了 FrameworkServletFrameworkServlet 又继承了 HttpServletBeanHttpServletBean 又继承了 HttpServlet ,因此 DispatcherServlet 就是传统 web 项目上的一个 Servlet

springsecurity简述执行流程 spring的执行过程_初始化_02

springsecurity简述执行流程 spring的执行过程_SpringMVC_03

springsecurity简述执行流程 spring的执行过程_初始化_04

那下面我们就以 Servlet 为切入点进行分析:

首先在 Servlet 中初始化时会触发 init() 方法,而这个方法就在 HttpServletBean 类中:

springsecurity简述执行流程 spring的执行过程_spring_05

在初始化方法中会进行子类的初始化工作,则会触发 FrameworkServlet 中的 initServletBean 方法:

springsecurity简述执行流程 spring的执行过程_SpringMVC_06

FrameworkServlet 主要调用了 initWebApplicationContext 初始化 WebApplicationContext,在 initWebApplicationContext 方法中会触发子类的 onRefresh 方法进行子类的初始化动作:

springsecurity简述执行流程 spring的执行过程_servlet_07


下面就可以来到 DispatcherServlet 中的 onRefresh 方法下:

springsecurity简述执行流程 spring的执行过程_spring_08

使用 initStrategies 方法进行组件的初始化操作,其中 initStrategies 方法的源码如下:

protected void initStrategies(ApplicationContext context) {
    //初始化文件上传解析器
    //默认赋值 org.springframework.web.multipart.support.StandardServletMultipartResolver
    initMultipartResolver(context);
    //初始化国际化语言解析器
    //默认赋值 org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
    initLocaleResolver(context);
    //初始化主题解析器
    //默认赋值 org.springframework.web.servlet.theme.FixedThemeResolver
    initThemeResolver(context);
    //初始化处理映射器
    initHandlerMappings(context);
    //初始化处理适配器
    initHandlerAdapters(context);
    //初始化异常处理解析器(@ControllerAdvice)
    //默认赋值 org.springframework.web.servlet.HandlerExceptionResolver接口子类
    //具体解析步骤
    initHandlerExceptionResolvers(context);
    //初始化视图转换器
    //默认赋值 org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
    initRequestToViewNameTranslator(context);
    //初始化视图解析器
    //默认赋值 org.springframework.web.servlet.ViewResolver接口子类
    initViewResolvers(context);
    //初始化flash管理器
    //默认赋值 org.springframework.web.servlet.support.SessionFlashMapManager
    initFlashMapManager(context);
}

可以看到进行了各种组件的初始化操作,这里我们主要看下 HandlerMappingsHandlerAdapters 是如何初始化的,首先看到 initHandlerMappings 方法中:

private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    // 从上下文中获取 handlerMapping,分为按类型获取,以及按名称获取
    // 是否检测所有的 handlerMapping , 默认为 true , 通过类型的方式从容器中获取 handlerMapping
    if (this.detectAllHandlerMappings) {
        // 获取全部的 handlerMapping
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        //handlerMapping 结果集不为空
        if (!matchingBeans.isEmpty()) {
            // 将映射器存入 handlerMappings 容器中
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            // 根据order配置对handlerMapping进行排序, 所有的HandlerMapping都实现了Ordered接口
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    } else {
        try {
            // 根据名称获取 handlerMapping
            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
            // 存入容器
            this.handlerMappings = Collections.singletonList(hm);
        } catch (NoSuchBeanDefinitionException ex) {
            // Ignore, we'll add a default HandlerMapping later.
        }
    }
    // Ensure we have at least one HandlerMapping, by registering
    // a default HandlerMapping if no other mappings are found.
    // 如果不存在 handlerMapping
    if (this.handlerMappings == null) {
        // 使用默认,默认策略不改动的情况下为: BeanNameUrl, RequestMapping, RouterFunction
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
    // 遍历全部的 handlerMapping
    for (HandlerMapping mapping : this.handlerMappings) {
        // 存在 handlerMapping 使用路径解析模式则赋值 parseRequestPath 为 true
        if (mapping.usesPathPatterns()) {
            this.parseRequestPath = true;
            break;
        }
    }
}

这里会去 Spring 容器中获取 handlerMapping ,如果不存在则会通过 getDefaultStrategies 方法获取一个默认的 handlerMappinggetDefaultStrategies 方法的源码如下:

protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
    if (defaultStrategies == null) {
        try {
            // Load default strategy implementations from properties file.
            // This is currently strictly internal and not meant to be customized
            // by application developers.
            //加载 DispatcherServlet 同级包中的 DispatcherServlet.properties
            ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException ex) {
            throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
        }
    }
    //获取接口名作为key
    String key = strategyInterface.getName();
    //在 DispatcherServlet.properties 中获取对应的 value 值
    String value = defaultStrategies.getProperty(key);
    // 如果存在 value
    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 Collections.emptyList();
    }
}

下面再看 initHandlerAdapters 方法,初始化处理适配器:

private void initHandlerAdapters(ApplicationContext context) {
    this.handlerAdapters = null;
    // 是否检查所有的 HandlerAdapter ,默认为 true
    if (this.detectAllHandlerAdapters) {
        // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
        // 根据类型获取全部的 HandlerAdapter
        Map<String, HandlerAdapter> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        // 如果结果集不为空
        if (!matchingBeans.isEmpty()) {
            // 将 HandlerAdapter 记入 handlerAdapters 容器中
            this.handlerAdapters = new ArrayList<>(matchingBeans.values());
            // We keep HandlerAdapters in sorted order.
            // 排序
            AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        }
    } else {
        try {
            // 根据名称获取 HandlerAdapter
            HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
            // 加入容器
            this.handlerAdapters = Collections.singletonList(ha);
        } catch (NoSuchBeanDefinitionException ex) {
            // Ignore, we'll add a default HandlerAdapter later.
        }
    }

    // Ensure we have at least some HandlerAdapters, by registering
    // default HandlerAdapters if no other adapters are found.
    // 如果不存在 HandlerAdapter
    if (this.handlerAdapters == null) {
        // 使用默认值
        this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
        if (logger.isTraceEnabled()) {
            logger.trace("No HandlerAdapters declared for servlet '" + getServletName() +
                    "': using default strategies from DispatcherServlet.properties");
        }
    }
}

在该方法中,同样也是会先去 Spring 容器中获取,如果获取不到,则同样使用 getDefaultStrategies 创建一个默认的 HandlerAdapter

2.2 请求执行操作

Servlet 中请求进来后,会根据请求类型的不同触发相应的方法,比如 doGet()doPost() 方法,这些方法在 FrameworkServlet 中:

springsecurity简述执行流程 spring的执行过程_servlet_09

可以看到,都调用了当前类的 processRequest 方法,在该方法中,则主要触发了子类的 doService 方法:

springsecurity简述执行流程 spring的执行过程_servlet_10

下面主要来看 DispatcherServlet 中的 doService 方法:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 记录请求日志
    logRequest(request);

    // 保存 request 属性,用于请求执行完属性清理后的属性恢复
    Map<String, Object> attributesSnapshot = null;
    // 当为 include 请求时,对 request 的 Attribute 做快照备份
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap<>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
            String attrName = (String) attrNames.nextElement();
            // 判断 是否开启属性清理功能  或者 属性名的前缀为 org.springframework.web.servlet
            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());

    // 如果 flashMapManager 不为空
    if (this.flashMapManager != null) {
        // 用于在 redirect 记录参数信息
        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());
        // 记录 flushManager
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    }

    // 是否进行路径解析(默认不进行)
    RequestPath requestPath = null;
    if (this.parseRequestPath && !ServletRequestPathUtils.hasParsedRequestPath(request)) {
        requestPath = ServletRequestPathUtils.parseAndCache(request);
    }

    try {
        // 主要处理逻辑
        doDispatch(request, response);
    } finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            // Restore the original attribute snapshot, in case of an include.
            // request属性恢复
            if (attributesSnapshot != null) {
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
        // 原 request 请求路径恢复
        if (requestPath != null) {
            ServletRequestPathUtils.clearParsedRequestPath(request);
        }
    }
}

该方法中主要则进行了一些属性的记录,主要逻辑则调用了 doDispatch 方法,下面进到 doDispatch 方法中:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //请求对象
    HttpServletRequest processedRequest = request;
    //处理请求的处理器链(包含 handler 和对应的 Interceptor)
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    //获取异步处理管理器,servlet3.0后支持异步处理
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        //  Model 和 View 的容器
        ModelAndView mv = null;
        // 处理请求 过程中,抛出的异常
        Exception dispatchException = null;

        try {
            // 检查是不是上传文件
            // 检查请求头中 Content-Type 属性是否为 multipart/form-data or multipart/ 开头
            // 如果是文件上传则构建一个 StandardMultipartHttpServletRequest 对象
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // Determine handler for the current request.
            // 根据 request 找到 handler
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
                // 找不到,报404错误
                noHandlerFound(processedRequest, response);
                return;
            }

            // Determine handler adapter for the current request.
            // 根据 handler 找到 handlerAdapter 适配器
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // Process last-modified header, if supported by the handler.
            // 获取请求方式
            String method = request.getMethod();
            // 处理 GET,HEAD 请求的  Last-Modified
            // 浏览器第一次跟服务器请求资源时(GET,HEAD请求),服务器的响应头会包含 Last-Modified属性
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                //获取最后修改时间
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                //调用checkNotModified方法验证 http 请求头中的“If-Modified-Since”的时间进行对比,判断页面是否更新过。
                //如果有更新才执行具体的Controller, 没有更新则响应 304 状态码信息(HTTP 304: Not Modified )
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                    return;
                }
            }

            // 调用拦截器的preHandle方法,若返回false,处理结束
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // Actually invoke the handler.
            // 调用 handler 处理请求,获取 ModelAndView 对象
            // controller 便是在此处执行的
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            // 如果异步正在执行,直接返回
            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            // 当 view 为空时, 比如 Handler 返回值 为 void, 则根据 request 设置一个默认 view
            applyDefaultViewName(processedRequest, mv);
            // 调用拦截器的 postHandle 方法
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        } catch (Exception ex) {
            dispatchException = ex;
        } catch (Throwable err) {
            // As of 4.3, we're processing Errors thrown from handler methods as well,
            // making them available for @ExceptionHandler methods and other scenarios.
            dispatchException = new NestedServletException("Handler dispatch failed", err);
        }
        // 处理上面处理之后的结果 (包括 处理异常,渲染页面,发出完成通知触发  Interceptor 的 afterCompletion)
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    } catch (Exception ex) {
        // 调用拦截器的 afterCompletion 方法
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    } catch (Throwable err) {
        triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", err));
    } finally {
        //对于异步处理的情况,调用异步处理的拦截器 AsyncHandlerInterceptor 的 afterConcurrentHandlingStarted 方法
        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.
            // 对于multipart的请求,清理资源,比如文件上传的请求,
            // 在上传的过程中文件会被保存到临时文件中,这里就会对这些文件继续清理
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}

从该方法的执行逻辑,是不是和文章开头写的执行过程非常相似,没错,doDispatch 方法就是整个 SpringMVC 的核心逻辑方法,下面我们主要就该方法进行解析:

2.3 getHandler

在这里首先使用 getHandler方法找到相应的 handler 也就是 Controller,下面进入到该方法中看下逻辑:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        // 遍历 HandlerMapping 默认由优先级最高的 requestMappingHandlerMapping 来进行处理
        for (HandlerMapping mapping : this.handlerMappings) {
            //获取处理器
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

遍历了所有的处理器映射器HandlerMapping,调用他们的getHandler方法得到能够处理当前请求的HandlerExecutionChain对象, 这个对象中包含了 3 个信息:

  • handler:请求处理器,通常就是我们自定义的 controller 对象及方法
  • interceptorList:拦截器,当前请求匹配到的拦截器列表
  • interceptorIndex:拦截器索引,用来记录执行到第几个拦截器了

下面在进到 mapping.getHandler 方法下,看是如何获取的,这里则主要触发的 AbstractHandlerMapping 类下的 getHandler 方法:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	// 模板方法,留给子类实现
	Object handler = getHandlerInternal(request);
	if (handler == null) {
		//handler为空获取默认的处理器 默认的 handler 也为 null
		handler = getDefaultHandler();
	}
	if (handler == null) {
		return null;
	}
	// handler 如果是字符串对象,则通过 Spring 容器尝试获取 Handler 实例
	if (handler instanceof String) {
		String handlerName = (String) handler;
		// 获取 bean 实例
		handler = obtainApplicationContext().getBean(handlerName);
	}

	//获取 HandlerExecutionChain 对象 ,包含 handler 和对应的 Interceptor
	HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

	if (logger.isTraceEnabled()) {
		logger.trace("Mapped to " + handler);
	}
	else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
		logger.debug("Mapped to " + executionChain.getHandler());
	}
	//跨域处理
	if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
		// cors 的检查请求
		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;
}

在该方法中,首先则调用子类的 getHandlerInternal 方法获取到 handler 其实是 HandlerMethod 对象,最后生成了一个 HandlerExecutionChain 封装对象,这里看下 getHandlerInternal 方法的逻辑,该方法在 AbstractHandlerMethodMapping 类下:

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
	// 获取请求路径
	String lookupPath = initLookupPath(request);
	// 映射存储器,尝试获取锁
	this.mappingRegistry.acquireReadLock();
	try {
		// 通过路径和请求找到 HandlerMethod
		HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
		// 如果找到则创建一个新的 HandlerMethod 返回
		return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
	}
	finally {
		// 放行锁
		this.mappingRegistry.releaseReadLock();
	}
}

首先会拿到请求路径,然后通过 lookupHandlerMethod 方法根据路径找到相应的 HandlerMethod ,下面是该方法的逻辑:

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
	List<Match> matches = new ArrayList<>();
	// 根据 loopuPath 获取对应 RequestInfoMapping 对象集合
	List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
	if (directPathMatches != null) {
		// 将找到的 RequestInfoMapping 添加到容器缓存
		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) {
			// 数量大于1的话进行排序后取第一个 HandlerMethod 包装类,请求条件数量多的优先
			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)) {
				return PREFLIGHT_AMBIGUOUS_MATCH;
			}
			// 取第二个最优匹配
			Match secondBestMatch = matches.get(1);
			// 前两个最优匹配一致,则会抛出异常
			if (comparator.compare(bestMatch, secondBestMatch) == 0) {
				Method m1 = bestMatch.handlerMethod.getMethod();
				Method m2 = secondBestMatch.handlerMethod.getMethod();
				String uri = request.getRequestURI();
				throw new IllegalStateException(
						"Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
			}
		}
		//设置 HandlerMethod 的 request 属性
		request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
		// 路径变量处理
		handleMatch(bestMatch.mapping, lookupPath, request);
		return bestMatch.handlerMethod;
	}
	else {
		return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
	}
}

主要还是根据 loopuPath 获取对应 RequestInfoMapping 对象集合。

下面再回到 DispatcherServlet 中,获取到 HandlerExecutionChain 对象后,如果没有找到相应的 handler ,则无该接口即返回 404

springsecurity简述执行流程 spring的执行过程_java_11

接着则是使用 getHandlerAdapter 根据 handler 找到 handlerAdapter 适配器。

springsecurity简述执行流程 spring的执行过程_java_12

2.4 getHandlerAdapter

进入到 getHandlerAdapter 方法中:

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        // 遍历 handlerAdapters
        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");
}

这里遍历所有的 handlerAdapter 通过 adapter.supports 方法判断是否支持,如果支持则直接返回,最后如果都不支持的话则抛出异常,下面看下 adapter.supports 方法,在 AbstractHandlerMethodAdapter 类下:

public final boolean supports(Object handler) {
	//  handler 必须是 HandlerMethod 的子类
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

判断父类是HandlerMethod类型就可以了,其中 supportsInternal 主要触发的是 RequestMappingHandlerAdapter 类的 supportsInternal 方法,在该类中直接返回的 true

springsecurity简述执行流程 spring的执行过程_spring_13

下面再回到 DispatcherServlet 中,获取到 HandlerAdapter 后,接着向下执行会根据请求方式处理 Last-Modified属性:

springsecurity简述执行流程 spring的执行过程_servlet_14


再向下执行则会调用拦截器的preHandle方法:

springsecurity简述执行流程 spring的执行过程_servlet_15

2.5 applyPreHandle

下面进入到 mappedHandler.applyPreHandle 方法中:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
	for (int i = 0; i < this.interceptorList.size(); i++) {
		HandlerInterceptor interceptor = this.interceptorList.get(i);
		// 拦截器前置处理
		if (!interceptor.preHandle(request, response, this.handler)) {
			// 前置处理返回 false 则执行拦截器中的 afterCompletion 方法
			triggerAfterCompletion(request, response, null);
			return false;
		}
		this.interceptorIndex = i;
	}
	return true;
}

这里直接获取到前面拿到的所有的拦截器,并触发 preHandle 方法,如果返回了 false,则表示在拦截器中就截断了,这里直接调用拦截器的 afterCompletion 方法。

再回到 DispatcherServlet 中,如果拦截器中的 preHandle 方法返回了 false ,那这里也没必要向下走了,直接 return 结束执行。

再向下执行的话,则来到了 ha.handle 中,这里则主要调用 handler 处理请求,获取 ModelAndView 对象,Controller 便是在此处执行的:

springsecurity简述执行流程 spring的执行过程_spring_16

2.6 handle

该方法主要触发的是 AbstractHandlerMethodAdapter 类下的 handle 方法:

springsecurity简述执行流程 spring的执行过程_SpringMVC_17

这里又主要调用了子类的 handleInternal 方法,其实是 RequestMappingHandlerAdapter 类的 handleInternal 方法:

protected ModelAndView handleInternal(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	// 基于控制器的方法执行时,不论返回值是多少,都会被处理成 ModelAndView
	ModelAndView mav;
	//检查请求中所支持的方法和是否需要session
	checkRequest(request);

	// Execute invokeHandlerMethod in synchronized block if required.
	// 是否需要基于session来执行加锁执行
	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
			// 没有session,则直接运行
			mav = invokeHandlerMethod(request, response, handlerMethod);
		}
	}
	else {
		// No synchronization on session demanded at all...
		// 没有同步要求,也是直接运行
		mav = invokeHandlerMethod(request, response, handlerMethod);
	}

	// 如果有 @SessionAttribute 注解,则阻止使用缓存
	if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
		// 检查处理器类,是否有 @SessionAttributes 注解(检查注释里面的 name 和 types参数)
		if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
			applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
		}
		else {
			// 给response设置缓存过期时间
			prepareResponse(response);
		}
	}
	return mav;
}

从该方法的逻辑中可以看出,实际执行逻辑又调用了 invokeHandlerMethod 方法,下面再来到该方法下:

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
		HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

	// 构建一个ServletWebRequest对象
	ServletWebRequest webRequest = new ServletWebRequest(request, response);
	try {
		// 参数绑定,主要功能就是实现参数,跟 String 之间的类型转换
		WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
		// 获取ModelFactory,主要用于在处理器具体处理之前,对 Model 进行初始化,处理完请求后,对 Model 参数进行更新
		ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
		// ServletInvocableHandlerMethod 继承自 HandlerMethod,主要用于参数绑定,处理请求  以及 返回值处理
		ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
		//如果参数解析器不为空
		if (this.argumentResolvers != null) {
			// 设置参数解析器
			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
		}
		// 如果返回值处理器不为空
		if (this.returnValueHandlers != null) {
			// 设置返回值处理器
			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
		}
		// 设置参数绑定工厂
		invocableMethod.setDataBinderFactory(binderFactory);
		// 设置 parameterNameDiscoverer
		invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

		// 创建一个 ModelAndViewContainer,用于保存 Model 和 View
		ModelAndViewContainer mavContainer = new ModelAndViewContainer();
		// 将 FlashMap 中的数据,添加到Model
		mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
		// 使用modelFactory 将 sessionAttributes 和 注释了 @ModelAttribute的方法的参数设置到 Model
		modelFactory.initModel(webRequest, mavContainer, invocableMethod);
		// 对 ignoreDefaultModelOnRedirect进行设置
		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;
		}
		//返回 ModelAndView
		return getModelAndView(mavContainer, modelFactory, webRequest);
	}
	finally {
		webRequest.requestCompleted();
	}
}

该方法则是具体执行请求的处理,首先通过 getDataBinderFactory 方法进行参数的绑定,下面看下该方法的逻辑:

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
	Class<?> handlerType = handlerMethod.getBeanType();
	// 检查当前 Handler中的InitBinger方法 是否已经再缓存中
	Set<Method> methods = this.initBinderCache.get(handlerType);
	// 如果没有,则查找 并设置到缓存中
	if (methods == null) {
		methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
		this.initBinderCache.put(handlerType, methods);
	}
	// 定义保存 InitBinder方法的临时变量
	List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
	// Global methods first
	// 将所有符合条件的全局 InitBinder方法添加到 initBinderMethods
	this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
		if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
			Object bean = controllerAdviceBean.resolveBean();
			for (Method method : methodSet) {
				initBinderMethods.add(createInitBinderMethod(bean, method));
			}
		}
	});
	// 将当前 Handler中的  initBinder方法添加到 initBinderMethods中
	for (Method method : methods) {
		Object bean = handlerMethod.getBean();
		initBinderMethods.add(createInitBinderMethod(bean, method));
	}
	// 创建 DataBinderFactory并返回
	return createDataBinderFactory(initBinderMethods);
}

再回到 invokeHandlerMethod 方法中,继续下面看,会创建一个 ModelAndViewContainer对象,用于保存 ModelView,后面该对象则给到了 invokeAndHandle 方法,做执行并处理请求的逻辑,下面进入到 invokeAndHandle 方法:

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	// 使用父类的方法,执行请求
	Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
	// 处理 @ResponseStatus 注解
	setResponseStatus(webRequest);

	// 处理返回值
	if (returnValue == null) {
		// 判断如果 request 的 notModified为真 或者 @ResponseStatus 存在,或者 mavContainer 的 requestandled 为 true
		if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
			//如果是 not modified 类型请求则进行缓存失效
			disableContentCachingIfNecessary(webRequest);
			//请求设置被完整处理
			mavContainer.setRequestHandled(true);
			return;
		}
	}
	// 如果 returnValue 不为空,并且 @ResponseStatus 注解里面有 reason,则也设置为请求已经处理,并返回
	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;
	}
}

在该方法中实际的执行请求则又调用了父类的的 invokeForRequest 方法,就是 InvocableHandlerMethod 类下的 invokeForRequest 方法:

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);
}

这里通过 getMethodArgumentValues 方法解析出方法所需要的参数:

protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
		Object... providedArgs) throws Exception {

	// 获取方法的参数,在HandlerMethod中
	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设置参数名解析器
		parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
		// 如果相应类型的参数 已经在proivdedArgs中提供了,则直接设置到 parameter
		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;
}

在回到 invokeForRequest 方法,继续向下,则采用反射 invoke 方式执行方法,可以看下 doInvoke 的逻辑:

protected Object doInvoke(Object... args) throws Exception {
	// 先使用反射将之强制变为可用
	ReflectionUtils.makeAccessible(getBridgedMethod());
	try {
		// 通过反射,调用bean的对应方法
		return getBridgedMethod().invoke(getBean(), args);
	}
	catch (IllegalArgumentException ex) {
		assertTargetBean(getBridgedMethod(), getBean(), args);
		String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
		throw new IllegalStateException(formatInvokeError(text, args), ex);
	}
	catch (InvocationTargetException ex) {
		// Unwrap for HandlerExceptionResolvers ...
		Throwable targetException = ex.getTargetException();
		if (targetException instanceof RuntimeException) {
			throw (RuntimeException) targetException;
		}
		else if (targetException instanceof Error) {
			throw (Error) targetException;
		}
		else if (targetException instanceof Exception) {
			throw (Exception) targetException;
		}
		else {
			throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
		}
	}
}

到这已经通过反射执行了 Controller 中的具体方法。

下面再回到 invokeAndHandle 方法下,这里将实际handler方法的返回,最后通过 returnValueHandlers.handleReturnValue 执行返回值的处理:

springsecurity简述执行流程 spring的执行过程_spring_18

进入 returnValueHandlers.handleReturnValue 方法下:

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);
}

这里又主要触发了 handler.handleReturnValue 方法,主要调用的子类的实现方法,这里的实现比较多:

springsecurity简述执行流程 spring的执行过程_spring_19

主要看下 ViewNameMethodReturnValueHandler 解析器下的 handleReturnValue 方法,这个使用的比较多:

public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
		ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

	if (returnValue instanceof CharSequence) {
		String viewName = returnValue.toString();
		// 如果返回值为String,则将其设置到 mavContainer 的 view 中
		mavContainer.setViewName(viewName);
		if (isRedirectViewName(viewName)) {
			mavContainer.setRedirectModelScenario(true);
		}
	}
	else if (returnValue != null) {
		// should not happen
		throw new UnsupportedOperationException("Unexpected return type: " +
				returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
	}
	// void 返回值,什么也不处理
}

这里会将结果值填充至 ModelAndViewContainer 中的 viewName 属性中。

下面再回到 invokeHandlerMethod 方法中,通过 invocableMethod.invokeAndHandle 已经将返回值放入到 mavContainer 中了,最后通过 getModelAndView 方法获取了一个 ModelAndView

springsecurity简述执行流程 spring的执行过程_SpringMVC_20


进入到该方法下:

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
		ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

	// 更新Model,包括设置 SessionAttributes 和 给Model 设置 BindingResult
	modelFactory.updateModel(webRequest, mavContainer);
	// 请求被完整处理
	if (mavContainer.isRequestHandled()) {
		return null;
	}
	// 获取ModelMap
	ModelMap model = mavContainer.getModel();
	//获取ModelAndView对象 封装请求对应视图和数据
	ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());
	if (!mavContainer.isViewReference()) {
		//设置视图
		mav.setView((View) mavContainer.getView());
	}
	// flash属性填充
	if (model instanceof RedirectAttributes) {
		Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		if (request != null) {
			RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
		}
	}
	return mav;
}

直接创建了一个 ModelAndView 对象,并进行了属性的渲染,到这一步就拿到了 ha.handle 方法的主要目标 ModelAndView 了。

下面再回到 DispatcherServlet 中,继续向下走,如果 ModelAndView为空时, 比如 Handler 返回值为 void, 则根据 request 设置一个默认 view

springsecurity简述执行流程 spring的执行过程_servlet_21

再向下走的话则会调用拦截器的 postHandle 方法:

2.7 postHandle

进入到 mappedHandler.applyPostHandle 方法下:

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
		throws Exception {

	for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
		HandlerInterceptor interceptor = this.interceptorList.get(i);
		// 拦截器后置处理
		interceptor.postHandle(request, response, this.handler, mv);
	}
}

和前面 applyPreHandle 方法类似,遍历当前的拦截器,触发后置处理。

再回到 DispatcherServlet 中,再向下执行使用 processDispatchResult 方法,处理上面返回之后的结果:

springsecurity简述执行流程 spring的执行过程_spring_22

2.8 processDispatchResult

进入到该方法下:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
                                   @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
                                   @Nullable Exception exception) throws Exception {
    //是否为错误视图
    boolean errorView = false;

    // 如果存在异常
    if (exception != null) {
        // ModelAndViewDefiningException 异常处理
        if (exception instanceof ModelAndViewDefiningException) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        } else {
            // 其他异常处理
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            // 统一异常处理,并未阻断流程
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }

    // Did the handler return a view to render?
    // 视图渲染
    if (mv != null && !mv.wasCleared()) {
        // 渲染视图,具体在 render方法中执行
        render(mv, request, response);
        if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    } else {
        if (logger.isTraceEnabled()) {
            logger.trace("No view rendering, null ModelAndView returned.");
        }
    }

    if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        // Concurrent handling started during a forward
        return;
    }

    if (mappedHandler != null) {
        // Exception (if any) is already handled..
        // 发出请求处理完成的通知,触发 Interceptor 的 afterCompletion
        mappedHandler.triggerAfterCompletion(request, response, null);
    }
}

在该方法中进行了视图的渲染,并在最后触发了 InterceptorafterCompletion,这里看下视图渲染方法 render

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // Determine locale for request and apply it to the response.
    Locale locale =
            (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
    response.setLocale(locale);

    View view;
    String viewName = mv.getViewName();
    if (viewName != null) {
        // We need to resolve the view name.
        view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
                    "' in servlet with name '" + getServletName() + "'");
        }
    } else {
        // No need to lookup: the ModelAndView object contains the actual View object.
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
                    "View object in servlet with name '" + getServletName() + "'");
        }
    }

    // Delegate to the View object for rendering.
    if (logger.isTraceEnabled()) {
        logger.trace("Rendering view [" + view + "] ");
    }
    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        // 视图解析
        view.render(mv.getModelInternal(), request, response);
    } catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Error rendering view [" + view + "]", ex);
        }
        throw ex;
    }
}

在该方法中有主要调用了 view.render 完成视图解析,该方法则是 AbstractView 类下的 render 方法:

public void render(@Nullable Map<String, ?> model, HttpServletRequest request,
		HttpServletResponse response) throws Exception {

	if (logger.isDebugEnabled()) {
		logger.debug("View " + formatViewName() +
				", model " + (model != null ? model : Collections.emptyMap()) +
				(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
	}

	//用于把参数的模型 与内置模型属性合并
	//合并顺序为:本视图的所有静态属性、当前请求的路径,传入的模型参数及封装好的请清求上下文
	//请求上下文中包含了主题源与信息源的相关内容
	//暴露的这些属性可以在后续处理中使用,以实现各种功能
	Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
	// 为视图设置相应的请求头
	prepareResponse(request, response);
	//将model 与视图进行整合
	renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}

这里进行了模型属性的合并,最终使用 renderMergedOutputModel 方法将model 与视图进行整合,该方法为抽象方法,由子类实现具体逻辑:

springsecurity简述执行流程 spring的执行过程_java_23


这里主要看 InternalResourceView 下的 renderMergedOutputModel 方法:

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

	// 将模型对象作为请求属性公开
	exposeModelAsRequestAttributes(model, request);

	// Expose helpers as request attributes, if any.
	exposeHelpers(request);

	// Determine the path for the request dispatcher.
	// 获取分发视图的路径
	String dispatcherPath = prepareForRendering(request, response);

	// Obtain a RequestDispatcher for the target resource (typically a JSP).
	// 构造jsp视图请求分发器
	RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
	if (rd == null) {
		throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
				"]: Check that the corresponding file exists within your web application archive!");
	}

	// 如果已包含或响应已提交,则执行包含,否则执行转发
	if (useInclude(request, response)) {
		response.setContentType(getContentType());
		if (logger.isDebugEnabled()) {
			logger.debug("Including [" + getUrl() + "]");
		}
		rd.include(request, response);
	}

	else {
		// Note: The forwarded resource is supposed to determine the content type itself.
		if (logger.isDebugEnabled()) {
			logger.debug("Forwarding to [" + getUrl() + "]");
		}
		// 转发
		rd.forward(request, response);
	}
}

下面再回到 DispatcherServlet 中,再继续向下看,如果发生了异常,则触拦截器的 afterCompletion 方法,将异常传递出去:

springsecurity简述执行流程 spring的执行过程_SpringMVC_24


最后在 finally 中判断是否异步或文件上传,进行结尾操作:

springsecurity简述执行流程 spring的执行过程_servlet_25