zoukankan      html  css  js  c++  java
  • Spring MVC之DispatcherServlet初始化

      今天在整合工作流activiti5.14时,部署到Tomcat中启动时看到console输出的信息中有如下信息,

    2017-02-16 14:43:11,161 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
    2017-02-16 14:43:11,161 DEBUG [org.springframework.web.context.support.XmlWebApplicationContext] - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@13b070c]
    2017-02-16 14:43:11,161 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'lifecycleProcessor'
    2017-02-16 14:43:11,163 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
    2017-02-16 14:43:11,164 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Creating instance of bean 'org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver'
    2017-02-16 14:43:11,166 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Finished creating instance of bean 'org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver'
    2017-02-16 14:43:11,167 DEBUG [org.springframework.web.servlet.DispatcherServlet] - Unable to locate LocaleResolver with name 'localeResolver': using default [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@109800a]
    2017-02-16 14:43:11,169 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Creating instance of bean 'org.springframework.web.servlet.theme.FixedThemeResolver'

    于是到网上查了下。

      下面的内容转自:zhangwei_david,访问地址:http://wujiu.iteye.com/blog/2170778,感谢zhangwei_david的分享!

      使用Spring MVC 时,需要在web.xml中配置DispatchServlet,这个DispatchServlet可以看成一个控制器的具体实现。作为一个控制器所有的请求都要通过它来处理,进行转发、匹配、数据处理后并转由页面进行展示。因此DispatchServlet是Spring MVC的核心部分。    

          在完成ContextLoaderListener的初始化后,Web容器开始初始化DispatcherServlet,这个初始化的启动与在web.xml中对载入次序的定义有关。DispathcerServlet会建立自己的上下文来持有Spring MVC的Bean,在建立这个自己的IOC容器时,会从ServletContext中得到根上下文作为自己持有上下文的双亲上下文。有了这个根上下文再对自己持有的上下文进行初始化,最后将自己持有的上下文保存到ServletContext中。

         首先看看DispatcherSerlvet的继承关系:DispatcherServlet继承自FrameworkServlet,而FrameworkServet继承自HttpServletBean.HttpServletBean有继承了HttpServlet.

        DispatcherServlet动作大致可以分为两个部分:初始化部分由initServletBean()启动,通过initWebApplicationContext()方法调用DispatcherServlet的initStrategies方法。在这个方法里,DispatcherServlet对MVC的其他部分进行了初始化,比如handlerMapping,ViewResolver;另一个部分是对Http的请求进行响应,作为一个Servlet,web容器会调用Servlet的doGet()和doPost()方法,在经过FrameServlet的processRequest()简单处理后,会调用DispatcherServlet的doService()方法,在这个方法中封装了doDispatch().

         在这里主要介绍初始化部分。

        作为Servlet, DispatcherServlet的启动过程和Servlet启动过程是相联系的。在Servlet的初始化过程中,Servlet的init方法被调用,已进行初始化。

    HttppServletBean.init()->FrameworkServlet.initWebApplicationContext()->DispatcherServlet.onRefresh().

    onRefresh 的源码是:

    1 /** 
    2  * This implementation calls {@link #initStrategies}. 
    3  */  
    4 @Override  
    5 protected void onRefresh(ApplicationContext context) {  
    6     initStrategies(context);  
    7 } 

      而initStrategies(context)的源码如下:

     1 protected void initStrategies(ApplicationContext context) {  
     2     //初始化多媒体解析器  
     3     initMultipartResolver(context);  
     4     //初始化位置解析器  
     5     initLocaleResolver(context);  
     6     //初始化主题解析器  
     7     initThemeResolver(context);  
     8     //初始化HandlerMappings  
     9     initHandlerMappings(context);  
    10     // 初始化HandlerAdapters  
    11     initHandlerAdapters(context);  
    12     //初始化异常解析器  
    13     initHandlerExceptionResolvers(context);  
    14     //初始化请求到视图名转换器  
    15     initRequestToViewNameTranslator(context);  
    16     //初始化视图解析器  
    17     initViewResolvers(context);  
    18     //初始化FlashMapManager  
    19     initFlashMapManager(context);  
    20 }  

      通过initMultipartResover进行初始化多媒体解析器,如果在配置文件中没有配置id为multipartResolver的bean则没有提供多媒体处理器。

     1 /** 
     2      * Initialize the MultipartResolver used by this class. 
     3      * <p>If no bean is defined with the given name in the BeanFactory for this namespace, 
     4      * no multipart handling is provided. 
     5      */  
     6     private void initMultipartResolver(ApplicationContext context) {  
     7         try {  
     8             this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);  
     9             if (logger.isDebugEnabled()) {  
    10                 logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");  
    11             }  
    12         }  
    13         catch (NoSuchBeanDefinitionException ex) {  
    14             // Default is no multipart resolver.  
    15             this.multipartResolver = null;  
    16             if (logger.isDebugEnabled()) {  
    17                 logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +  
    18                         "': no multipart request handling provided");  
    19             }  
    20         }  
    21     }  

      通过initLocaleResolver方法进行localeResolver的初始化,如果没有配置指定id为localeResolver的bean则使用AcceptHeaderLocaleResolver的位置解析器。

     1 /* Initialize the LocaleResolver used by this class.  
     2  * <p>If no bean is defined with the given name in the BeanFactory for this namespace,  
     3  * we default to AcceptHeaderLocaleResolver.  
     4  */  
     5 private void initLocaleResolver(ApplicationContext context) {  
     6     try {  
     7         this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);  
     8         if (logger.isDebugEnabled()) {  
     9             logger.debug("Using LocaleResolver [" + this.localeResolver + "]");  
    10         }  
    11     }  
    12     catch (NoSuchBeanDefinitionException ex) {  
    13         // We need to use the default.  
    14         this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);  
    15         if (logger.isDebugEnabled()) {  
    16             logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +  
    17                     "': using default [" + this.localeResolver + "]");  
    18         }  
    19     }  
    20 }  

      initThemeResolver初始化主题解析器,如果没有配置指定id的为themeResolver的bean 则使用FixedThemeResolver主题解析器。

     1 /** 
     2  * Initialize the ThemeResolver used by this class. 
     3  * <p>If no bean is defined with the given name in the BeanFactory for this namespace, 
     4  * we default to a FixedThemeResolver. 
     5  */  
     6 private void initThemeResolver(ApplicationContext context) {  
     7     try {  
     8         this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);  
     9         if (logger.isDebugEnabled()) {  
    10             logger.debug("Using ThemeResolver [" + this.themeResolver + "]");  
    11         }  
    12     }  
    13     catch (NoSuchBeanDefinitionException ex) {  
    14         // We need to use the default.  
    15         this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);  
    16         if (logger.isDebugEnabled()) {  
    17             logger.debug(  
    18                     "Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" +  
    19                             this.themeResolver + "]");  
    20         }  
    21     }  
    22 } 

      初始化HandlerMapping,这个handlerMapping的作用是为Http请求找到相应的控制器,从而利用这些控制器去完成http请求的数据处理工作。这些控制器和http的请求时对应的。DispatcherServlet中handlerMapping的初始化过程中的具体实现如下。在HandlerMapping的初始化过程中,把Bean配置文件中配置好的handlerMapping从IOC容器中取出。

     1 /** 
     2  * Initialize the HandlerMappings used by this class. 
     3  * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace, 
     4  * we default to BeanNameUrlHandlerMapping. 
     5  */  
     6 private void initHandlerMappings(ApplicationContext context) {  
     7     this.handlerMappings = null;  
     8   
     9     if (this.detectAllHandlerMappings) {  
    10         // 在应用上下文包括其祖先上下文中查找所有HandlerMappings  
    11         Map<String, HandlerMapping> matchingBeans =  
    12                 BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);  
    13         //如果matchingBeans这个map是不为空,则创建一个新的ArrayList  
    14         if (!matchingBeans.isEmpty()) {  
    15             this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());  
    16             //并对其进行排序  
    17             OrderComparator.sort(this.handlerMappings);  
    18         }  
    19     }  
    20     else {  
    21         try {  
    22             //从应用上下文中查找所有的HandlerMapping  
    23             HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);  
    24             this.handlerMappings = Collections.singletonList(hm);  
    25         }  
    26         catch (NoSuchBeanDefinitionException ex) {  
    27             // Ignore, we'll add a default HandlerMapping later.  
    28         }  
    29     }  
    30   
    31     // Ensure we have at least one HandlerMapping, by registering  
    32     // a default HandlerMapping if no other mappings are found.  
    33     if (this.handlerMappings == null) {  
    34         // 如果没有配置HandlerMapping 则使用默认的HandlerMapping 策略  
    35         this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);  
    36         if (logger.isDebugEnabled()) {  
    37             logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");  
    38         }  
    39     }  
    40 }  

      经过上述的处理过程,handlerMapping已经初始化完成,handlerMapping中就已经获取了在BeanDefinition中配置的映射关系。

      通过initHandlerAdapters进行初始化HandlerAdapter,如果没有配置HandlerAdapter则使用SimpleControllerHandlerAdapter。

     1 /** 
     2      * Initialize the HandlerAdapters used by this class. 
     3      * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace, 
     4      * we default to SimpleControllerHandlerAdapter. 
     5      */  
     6     private void initHandlerAdapters(ApplicationContext context) {  
     7         this.handlerAdapters = null;  
     8   
     9         if (this.detectAllHandlerAdapters) {  
    10             // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.  
    11             Map<String, HandlerAdapter> matchingBeans =  
    12                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);  
    13             if (!matchingBeans.isEmpty()) {  
    14                 this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values());  
    15                 // We keep HandlerAdapters in sorted order.  
    16                 OrderComparator.sort(this.handlerAdapters);  
    17             }  
    18         }  
    19         else {  
    20             try {  
    21                 HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);  
    22                 this.handlerAdapters = Collections.singletonList(ha);  
    23             }  
    24             catch (NoSuchBeanDefinitionException ex) {  
    25                 // Ignore, we'll add a default HandlerAdapter later.  
    26             }  
    27         }  
    28   
    29         // Ensure we have at least some HandlerAdapters, by registering  
    30         // default HandlerAdapters if no other adapters are found.  
    31         if (this.handlerAdapters == null) {  
    32             this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);  
    33             if (logger.isDebugEnabled()) {  
    34                 logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");  
    35             }  
    36         }  
    37     }  

      初始化异常处理器,如果没有配置指定Id为handlerExceptionResolver的Bean,默认是没有异常处理器。

     1 /** 
     2  * Initialize the HandlerExceptionResolver used by this class. 
     3  * <p>If no bean is defined with the given name in the BeanFactory for this namespace, 
     4  * we default to no exception resolver. 
     5  */  
     6 private void initHandlerExceptionResolvers(ApplicationContext context) {  
     7     this.handlerExceptionResolvers = null;  
     8   
     9     if (this.detectAllHandlerExceptionResolvers) {  
    10         // Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.  
    11         Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils  
    12                 .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);  
    13         if (!matchingBeans.isEmpty()) {  
    14             this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());  
    15             // We keep HandlerExceptionResolvers in sorted order.  
    16             OrderComparator.sort(this.handlerExceptionResolvers);  
    17         }  
    18     }  
    19     else {  
    20         try {  
    21             HandlerExceptionResolver her =  
    22                     context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);  
    23             this.handlerExceptionResolvers = Collections.singletonList(her);  
    24         }  
    25         catch (NoSuchBeanDefinitionException ex) {  
    26             // Ignore, no HandlerExceptionResolver is fine too.  
    27         }  
    28     }  
    29   
    30     // Ensure we have at least some HandlerExceptionResolvers, by registering  
    31     // default HandlerExceptionResolvers if no other resolvers are found.  
    32     if (this.handlerExceptionResolvers == null) {  
    33         this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);  
    34         if (logger.isDebugEnabled()) {  
    35             logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");  
    36         }  
    37     }  
    38 }  

      初始化请求到视图名称的转换器,如果不配置则使用默认的转换器。

     1 /** 
     2      * Initialize the RequestToViewNameTranslator used by this servlet instance. 
     3      * <p>If no implementation is configured then we default to DefaultRequestToViewNameTranslator. 
     4      */  
     5     private void initRequestToViewNameTranslator(ApplicationContext context) {  
     6         try {  
     7             this.viewNameTranslator =  
     8                     context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);  
     9             if (logger.isDebugEnabled()) {  
    10                 logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");  
    11             }  
    12         }  
    13         catch (NoSuchBeanDefinitionException ex) {  
    14             // We need to use the default.  
    15             this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);  
    16             if (logger.isDebugEnabled()) {  
    17                 logger.debug("Unable to locate RequestToViewNameTranslator with name '" +  
    18                         REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator +  
    19                         "]");  
    20             }  
    21         }  
    22     }  

      初始化视图解析器,如果没有配置视图解析器则使用默认的InternalResourceViewResolver视图解析器。

     1 /** 
     2      * Initialize the ViewResolvers used by this class. 
     3      * <p>If no ViewResolver beans are defined in the BeanFactory for this 
     4      * namespace, we default to InternalResourceViewResolver. 
     5      */  
     6     private void initViewResolvers(ApplicationContext context) {  
     7         this.viewResolvers = null;  
     8   
     9         if (this.detectAllViewResolvers) {  
    10             // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.  
    11             Map<String, ViewResolver> matchingBeans =  
    12                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);  
    13             if (!matchingBeans.isEmpty()) {  
    14                 this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());  
    15                 // We keep ViewResolvers in sorted order.  
    16                 OrderComparator.sort(this.viewResolvers);  
    17             }  
    18         }  
    19         else {  
    20             try {  
    21                 ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);  
    22                 this.viewResolvers = Collections.singletonList(vr);  
    23             }  
    24             catch (NoSuchBeanDefinitionException ex) {  
    25                 // Ignore, we'll add a default ViewResolver later.  
    26             }  
    27         }  
    28   
    29         // Ensure we have at least one ViewResolver, by registering  
    30         // a default ViewResolver if no other resolvers are found.  
    31         if (this.viewResolvers == null) {  
    32             this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);  
    33             if (logger.isDebugEnabled()) {  
    34                 logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");  
    35             }  
    36         }  
    37     }  

      获取默认设置,首先获取接口的名称,然后从DispatcherServlert.properties的配置文件中读取value,然后将其分割为字符串数组。

     1 /** 
     2      * Create a List of default strategy objects for the given strategy interface. 
     3      * <p>The default implementation uses the "DispatcherServlet.properties" file (in the same 
     4      * package as the DispatcherServlet class) to determine the class names. It instantiates 
     5      * the strategy objects through the context's BeanFactory. 
     6      * @param context the current WebApplicationContext 
     7      * @param strategyInterface the strategy interface 
     8      * @return the List of corresponding strategy objects 
     9      */  
    10     @SuppressWarnings("unchecked")  
    11     protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {  
    12         String key = strategyInterface.getName();  
    13         String value = defaultStrategies.getProperty(key);  
    14         if (value != null) {  
    15             String[] classNames = StringUtils.commaDelimitedListToStringArray(value);  
    16             List<T> strategies = new ArrayList<T>(classNames.length);  
    17             for (String className : classNames) {  
    18                 try {  
    19                     Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());  
    20                     Object strategy = createDefaultStrategy(context, clazz);  
    21                     strategies.add((T) strategy);  
    22                 }  
    23                 catch (ClassNotFoundException ex) {  
    24                     throw new BeanInitializationException(  
    25                             "Could not find DispatcherServlet's default strategy class [" + className +  
    26                                     "] for interface [" + key + "]", ex);  
    27                 }  
    28                 catch (LinkageError err) {  
    29                     throw new BeanInitializationException(  
    30                             "Error loading DispatcherServlet's default strategy class [" + className +  
    31                                     "] for interface [" + key + "]: problem with class file or dependent class", err);  
    32                 }  
    33             }  
    34             return strategies;  
    35         }  
    36         else {  
    37             return new LinkedList<T>();  
    38         }  
    39     }  

      DispatcherSerlvet.properties

     1 # Default implementation classes for DispatcherServlet's strategy interfaces.  
     2 # Used as fallback when no matching beans are found in the DispatcherServlet context.  
     3 # Not meant to be customized by application developers.  
     4   
     5 org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver  
     6   
     7 org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver  
     8   
     9 org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,  
    10     org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping  
    11   
    12 org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,  
    13     org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,  
    14     org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter  
    15   
    16 org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,  
    17     org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,  
    18     org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver  
    19   
    20 org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator  
    21   
    22 org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver  
    23   
    24 org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager  
  • 相关阅读:
    mysql增加字段,修改字段,增加索引等语句
    php获取post参数的几种方式
    微信小程序开发注意事项
    jQuery的deferred对象详解
    jquery.pagination.js的使用
    js实现一键复制
    PHP读取文件内容的五种方式
    3.3 模块的搜索路径
    3.2 py文件的两种功能
    3.1 模块的定义与分类,import,from...import
  • 原文地址:https://www.cnblogs.com/kylyww/p/6405888.html
Copyright © 2011-2022 走看看