再说springmvc的时候,我觉得有必要提一下servlet中filter,listener以及servlet都对应的有初始化方法。那么他们的执行顺序是怎样的呢?
在servlet容器的启动过程中,首先会优先调用listenner的contextInitialized方法。然后调用filter的init方法。当容器启动完成后。如果有请求进来,会对第一次请求调用对应的servlet的初始化方法,有且只执行一次。
在使用springmvc的功能的时候,首先通过在web.xml配置如下信息。该信息做了两件事,一件启动spring容器。一件创建了一个通用的url拦截dispatcherServlet。所有的url请求都会被dispatcherServerlt响应。正如其名称,他只是起到一个分发的作用。下面我们会分析
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> |
在之前的分析中。我们说到,spring在启动容器的时候会通过创建一个applicationContext。那么下面我们看下ContextLoaderListener做了什么事情。
ContextLoaderListenner 实现了ServletContextListener。在servlet容器启动过程中会调用contextInitialized(ServletContextEvent event)方法,在容器销毁过程中会调用contextDestroyed方法。下面我们看下contextInitialized方法
public void contextInitialized(ServletContextEvent event) { //根据event事件获取serverlet上下文 initWebApplicationContext(event.getServletContext()); }
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { //判断是否有多个contextLoader定义,如果当前的成功,该值存在 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); }
Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis();
try { // Store context in local instance variable, to guarantee that // 创建spring的上下文。 if (this.context == null) { this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { //默认为XmlWebApplicationContext 是继承自//ConfigurableWebApplicationContext,所以默认会调用此处 ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; 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 -> // determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } //生成id并且调用对应的refresh方法,refresh方法,和之前的大同//小异就不具体分析了 configureAndRefreshWebApplicationContext(cwac, servletContext); } } //创建成功,将spring的上下文放入到servlet的上下文中,便于后续获取使用 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); //判断类加载器,如果和当前线程的类加载器相同,直接放入到类变量中。由于是静态变量,该加载器下的所有的对象的值都是相同,否则就放到线程变量中 ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); }
if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); }
return this.context; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } }
|
下面我们看下具体的创建过程
protected WebApplicationContext createWebApplicationContext(ServletContext sc) { //首先从sc的上下文获取contextClass属性,如果没有返回 //则从ContextLoader.properties获取,具体代码查看ContextLoader的静态代码块 WebApplicationContext Class<?> contextClass = determineContextClass(sc); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } //利用反射,也就是调用无参构造函数,创建对象XmlWebApplicationContext return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); } |
通过上面分析,spring中的相关组件就已经加载到了对应的环境中了。下面我们看下dispatchServlet的功能。至于controller,service,以及component(其实controller以及service的注解都包含了Component注解,所以才被扫描)的加载请参看之前的逻辑,或者参看ClassPathBeanDefinitionScanner
查看DispatcherServlet的类图。从图中可以看出,DispatcherServlert实现了ApplicationContextAware,EnvironmentAware。那么spring容器在管理当前bean的时候会把applicationContext以及environment注入进来。但是你会很好奇,当前的servlet并不是被spring所管理的啊。他怎么注入的呢?其实他这里实现的接口并不会被spring注入。还记得我们上面分析的ContextLoaderListenner会优先于当前的servlet进行初始化,因此。Spring对应的applicationContext此时已经创建完成,并且通上面的这一行代码servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
放入了对应的servletContext中。
下面查看DispatchServlet的init方法
public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); }
//解析init-param并放入到对应的pvs中 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { //将当前对象封装成beanwrapper对象,这样就可以用spring的方式进行 //相关值的设置 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); //对Resource的对象注册一个解析器。 ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); initBeanWrapper(bw); //属性值注入。经过当前步骤。会把相关的setxxx在init-param配置会解析 //比如如果配置了contextConfigLocation则此时会填充 bw.setPropertyValues(pvs, true); } catch (BeansException ex) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); } throw ex; } }
// Let subclasses do whatever initialization they like. initServletBean();
if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } } |
下面我们看下initServletBean.上面只是对于一般的属性的注入。但是springmvc容器以及spring的上下文也没有加载引入
protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); } long startTime = System.currentTimeMillis();
try { //初始化springmvc的容器以及引入spring的容器 this.webApplicationContext = initWebApplicationContext(); //留给子类覆盖实现 initFrameworkServlet(); } catch (ServletException ex) { this.logger.error("Context initialization failed", ex); throw ex; } catch (RuntimeException ex) { this.logger.error("Context initialization failed", ex); throw ex; }
if (this.logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + elapsedTime + " ms"); } } |
下面我们进入对应的initWebApplicationContext方法
protected WebApplicationContext initWebApplicationContext() { //从servlet上下文获取对应的webapplicationContext。还记得上面我们说 //ContextLoaderLinstenner会将创建的WebApplicationContext放入到servlet的上下文 WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null;
if (this.webApplicationContext != null) { // 存在contextz直接使用 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 //设置spring的applicationContext为其父容器 // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } //属性上下文 configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // 根据contextAttribute加载applicationContext wac = findWebApplicationContext(); } if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); }
if (!this.refreshEventReceived) { //初始化hanldermapping,hanlderadpater等信息 onRefresh(wac); }
if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]"); } }
return wac; } |
//进入DispatcherServlet的onRefresh函数中
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context); }
/** * Initialize the strategy objects that this servlet uses. * <p>May be overridden in subclasses in order to initialize further strategy objects. */ protected void initStrategies(ApplicationContext context) { //附件上传解析器,查找名称为multipartResolver的Bean initMultipartResolver(context); //国际化解析器,查找名称为localeResolver的bean initLocaleResolver(context); //主题解析器 查找名称为themeResolver的bean initThemeResolver(context); //查找handlerMapping,首先查找实现了HandlerMapping接口的bean //否则查找名称为handlerMapping的 bean。最后还找不到,就去找 //DispatcherServlet.properties对应的hanlderMapping // BeanNameUrlHandlerMapping ,DefaultAnnotationHandlerMapping initHandlerMappings(context); //查找hanlderAdaters.逻辑同上面. //默认加载的HttpRequestHandlerAdapter, //SimpleControllerHandlerAdapter,AnnotationMethodHandlerAdapter initHandlerAdapters(context); //逻辑同上 initHandlerExceptionResolvers(context); //当controller没有返回ModelAndView对象或者往response(@ResponseBody的作用)中回写数据的时候,spring就会采用约定好的去查找一个逻辑视图名。 initRequestToViewNameTranslator(context); //初始化视图解析器,默认InternalResourceViewResolver //当controller把视图解析结果放到modelAndview中时,会选择对应的视图进行渲//染。怎么找到view的结果的呢,就是通过ViewResolver initViewResolvers(context); // 请求属性的暂存,比如在重定向的时候,可以把上一个请求的信息重定向到下//一个请求信息中 initFlashMapManager(context); } |
HttpRequestHandlerAdapter: 主要应用在基于http的远程调用上。
SimpleControllerHandlerAdapter:基于控制类接口的适配。实现了Controller接口的适配
AnnotationMethodHandlerAdapter:基于注解的适配
//初始化完成后,下面我们看下正式的request响应过程
进入DispatcherServlet的doGet,doPost方法,发现都是通过processRequest进行响应。进入对应的方法中
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 ex) { failureCause = ex; throw ex; } catch (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(); }
if (logger.isDebugEnabled()) { if (failureCause != null) { this.logger.debug("Could not complete request", failureCause); } else { if (asyncManager.isConcurrentHandlingStarted()) { logger.debug("Leaving response open for concurrent processing"); } else { this.logger.debug("Successfully completed request"); } } }
publishRequestHandledEvent(request, response, startTime, failureCause); } } |
下面我们进入doService中查看
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); }
// Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<String, Object>(); 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)); } } }
// Make framework objects available to handlers and view objects. 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());
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
try { doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } } |
进入到doDispatch中
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 { //查看请求的content-type是否以/multipart开头的,如果是需要转换当前的MultipartHttpServletRequest processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request);
// 查找handler。 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; }
// 根据handler查找对应的hanlderAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 处理 last-modified header头参数 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //应用拦截器的preHandle if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
// 执行 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) { return; } // 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); } 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 { 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); } } } } |
下面我们按照上面的逻辑一步步分析具体的执行过程。首先根据request获取对应的handler.
下面我们会按照开启注解的方式的handlermap和adapter讲解。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; } |
我们在配置文件中使用annotation-driven标签的时候会被解析。
通过AnnotationDrivenBeanDefinitionParser会帮我们注册RequestMappingHandlerMapping以及RequestMappingHandlerAdapter,ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver,ExceptionHandlerExceptionResolver
RequestMappingHandlerMapping实现了InitializingBean接口,在初始化的时候会调用其afterPropertiesSet方法。
@Override public void afterPropertiesSet() { initHandlerMethods(); }
/** * Scan beans in the ApplicationContext, detect and register handler methods. * @see #isHandler(Class) * @see #getMappingForMethod(Method, Class) * @see #handlerMethodsInitialized(Map) */ protected void initHandlerMethods() { if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } //获取到所有的bean String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null; try { beanType = getApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isDebugEnabled()) { logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex); } } //判断该bean是否有Controller注解或者RequestMapping注解 if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } } } handlerMethodsInitialized(getHandlerMethods()); }
protected void detectHandlerMethods(final Object handler) { Class<?> handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()); final Class<?> userType = ClassUtils.getUserClass(handlerType);
Map<Method, T> methods = MethodIntrospector.selectMethods(userType, new MethodIntrospector.MetadataLookup<T>() { @Override public T inspect(Method method) { return getMappingForMethod(method, userType); } });
if (logger.isDebugEnabled()) { logger.debug(methods.size() + " request handler methods found on " + userType + ": " + methods); } //将对应的urlpath和method对应保存起来。 for (Map.Entry<Method, T> entry : methods.entrySet()) { registerHandlerMethod(handler, entry.getKey(), entry.getValue()); } }
|
下面我们再看下具体的RequestMappingHandlerMapper中的getHanler的过程
进入到AbstractHandlerMapping 的getHandler中。
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //获取对应的handlerMapping.当前spring采用模板模式。 //该类的具体实现会在子类中。 Object handler = getHandlerInternal(request); if (handler == null) { //如果没有,使用默认的handlerMapping handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } //增加并封装hanlderExecutionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; } //从mappingRegistry获取对应的handler。上面说到registerHandlerMethod(handler, //entry.getKey(), entry.getValue());该方法就注册到mappingRegistry中 protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { //获取url。 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); } this.mappingRegistry.acquireReadLock(); try { HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); if (logger.isDebugEnabled()) { if (handlerMethod != null) { logger.debug("Returning handler method [" + handlerMethod + "]"); } else { logger.debug("Did not find handler method for [" + lookupPath + "]"); } } return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
|
现在找到了对应的handler。下面我们继续看,根据handler以及handlerAdapter执行对应的方法
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return handleInternal(request, response, (HandlerMethod) handler); }
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav; //检查当前方法是否支持并且查看是否有session checkRequest(request);
//查看是否需要在同步块中执行。 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 { //将当前的request封装成ServletWebRequest ServletWebRequest webRequest = new ServletWebRequest(request, response); //数据绑定工厂 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); //模型工厂 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); //下面的类是用来将request的请求解析成对应的入参 //以及对应的返回的函数的封装。 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); 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(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]"); } invocableMethod = invocableMethod.wrapConcurrentResult(result); } //执行正常的方法,即对参数进行转换以及对返回值进行处理 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; }
return getModelAndView(mavContainer, modelFactory, webRequest); }
|