15_springmvc

再说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);

         }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值