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  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM