通過xml配置SpringMVC注解DispatcherServlet初始化過程解析
xml方式初始化DispatcherServle配置
通過xml方式初始化DispatcherServlet時,xml文件中可以配置:
<mvc:annotation-driven />
或:
<mvc:annotation-driven > <!--設(shè)置響應(yīng)輸出字符集--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=utf-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
表示對MVC注解的支持。
該標(biāo)簽的解析工作最終會由AnnotationDrivenBeanDefinitionParser的parse方法完成,parse方法主要完成以下工作
- 注冊RequestMappingHandlerMapping的beanDefinition到WebApplication容器
- 注冊RequestMappingHandlerAdapter的beanDefinition到WebApplication容器,同時從xml文件解析其messageConverters的定義(這也是xml文件中messageConverters生效的原因)
- 注冊ExceptionHandlerExceptionResolver的beanDefinition到WebApplication容器
- 注冊ResponseStatusExceptionResolver的beanDefinition到WebApplication容器
- 注冊DefaultHandlerExceptionResolver的beanDefinition到WebApplication容器
根據(jù)beanDefinition創(chuàng)建對應(yīng)的bean
之后在容器refresh的過程中根據(jù)beanDefinition創(chuàng)建對應(yīng)的bean。
之后,在DispatcherServlet初始化的過程中,通過initStrategies初始化SpringMVC的相關(guān)“特殊類型的Bean”:
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
比如initHandlerMappings方法:
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. //首先通過beanFactoryUtils從Spring容器中,通過類型獲取 Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); //如果從容器中獲取到了bean,放入到handlerMappings中 if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); // We keep HandlerMappings in sorted order. AnnotationAwareOrderComparator.sort(this.handlerMappings); } } else { try { //通過名字和類型從容器獲取 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class); this.handlerMappings = Collections.singletonList(hm); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerMapping later. } } // Ensure we have at least one HandlerMapping, by registering // a default HandlerMapping if no other mappings are found. if (this.handlerMappings == null) { //從容器中沒有獲取到,才調(diào)用getDefaultStrategies獲取默認的、dispatcherServlet.properties文件中定義的 this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerMappings declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }
如果xml文件中不配置<mvc:annotation-driven />,也沒有 <mvc:default-servlet-handler />,則Spring容器中就不會有對應(yīng)的bean,這種情況下,才通過調(diào)用getDefaultStrategies方法,讀取DispatcherServlet.properties文件獲取該文件定義的默認HandlerMappings,完成創(chuàng)建,當(dāng)然,創(chuàng)建后也會放入Spring容器:
protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) { return context.getAutowireCapableBeanFactory().createBean(clazz); }
DefaultServletHandlerBeanDefinitionParser
xml文件中如果配置了 <mvc:default-servlet-handler />,SpringMVC啟動時解析 <mvc:default-servlet-handler />標(biāo)簽過程中會調(diào)用DefaultServletHandlerBeanDefinitionParser,其parse方法會將SimpleUrlHandlerMapping以及BeanNameUrlHandlerMapping注入到WebApplicationContext容器中,目的是通過SimpleUrlHandlerMapping來處理"/**"請求(轉(zhuǎn)交給DefaultServletHttpRequestHandler)。
這個處理有個副作用:由于SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping作為handlerMappings注入到容器中,分析DispatcherServlet的初始化方法initHandlerMappings的源碼可知:
DispatcherServlet.properties文件中默認的RequestMappingHandlerMapping不會被注入!
而RequestMappingHandlerMapping是具體負責(zé)SpringMVC注解解釋的,沒有了RequestMappingHandlerMapping,類似@Controller等SpringMVC注解就不會生效。
所以,其實SpringMVC默認情況下天生是可以支持SpringMVC注解的,只不過是 <mvc:default-servlet-handler />往往不可避免的需要配置(因為項目中總有靜態(tài)資源需要展示),但是加了 <mvc:default-servlet-handler />會導(dǎo)致SpringMVC的注解失效!
因此導(dǎo)致了,正常的SpringMVC項目的以下兩項配置往往需要成對出現(xiàn):
<mvc:annotation-driven /> <mvc:default-servlet-handler />
以上就是通過xml配置SpringMVC注解DispatcherServlet初始化過程解析的詳細內(nèi)容,更多關(guān)于xml配置SpringMVC注解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Spring Security中的HttpBasic登錄驗證模式
HttpBasic登錄驗證模式是Spring Security實現(xiàn)登錄驗證最簡單的一種方式,也可以說是最簡陋的一種方式,這篇文章主要介紹了Spring Security的HttpBasic登錄驗證模式,需要的朋友可以參考下2019-11-11Java中的關(guān)鍵字synchronized 詳解
這篇文章主要介紹了Java中的關(guān)鍵字synchronized,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03SpringSecurity實現(xiàn)前后端分離登錄token認證詳解
目前市面上比較流行的權(quán)限框架主要實Shiro和Spring Security,這兩個框架各自側(cè)重點不同,各有各的優(yōu)劣,本文將給大家詳細介紹SpringSecurity如何實現(xiàn)前后端分離登錄token認證2023-06-06解析Java的InputStream類并借助其讀取ppt文件
這篇文章主要介紹了Java的InputStream類并借助其讀取ppt文件,講到了InputStream類中一些常用的方法的問題,需要的朋友可以參考下2015-11-11feignclient?https?接口調(diào)用報證書錯誤的解決方案
這篇文章主要介紹了feignclient?https?接口調(diào)用報證書錯誤的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03