通過xml配置SpringMVC注解DispatcherServlet初始化過程解析
xml方式初始化DispatcherServle配置
通過xml方式初始化DispatcherServlet時(shí),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容器,同時(shí)從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獲取默認(rèn)的、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文件獲取該文件定義的默認(rèn)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啟動時(shí)解析 <mvc:default-servlet-handler />標(biāo)簽過程中會調(diào)用DefaultServletHandlerBeanDefinitionParser,其parse方法會將SimpleUrlHandlerMapping以及BeanNameUrlHandlerMapping注入到WebApplicationContext容器中,目的是通過SimpleUrlHandlerMapping來處理"/**"請求(轉(zhuǎn)交給DefaultServletHttpRequestHandler)。
這個處理有個副作用:由于SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping作為handlerMappings注入到容器中,分析DispatcherServlet的初始化方法initHandlerMappings的源碼可知:
DispatcherServlet.properties文件中默認(rèn)的RequestMappingHandlerMapping不會被注入!
而RequestMappingHandlerMapping是具體負(fù)責(zé)SpringMVC注解解釋的,沒有了RequestMappingHandlerMapping,類似@Controller等SpringMVC注解就不會生效。
所以,其實(shí)SpringMVC默認(rèn)情況下天生是可以支持SpringMVC注解的,只不過是 <mvc:default-servlet-handler />往往不可避免的需要配置(因?yàn)轫?xiàng)目中總有靜態(tài)資源需要展示),但是加了 <mvc:default-servlet-handler />會導(dǎo)致SpringMVC的注解失效!
因此導(dǎo)致了,正常的SpringMVC項(xiàng)目的以下兩項(xiàng)配置往往需要成對出現(xiàn):
<mvc:annotation-driven /> <mvc:default-servlet-handler />
以上就是通過xml配置SpringMVC注解DispatcherServlet初始化過程解析的詳細(xì)內(nèi)容,更多關(guān)于xml配置SpringMVC注解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java詳解實(shí)現(xiàn)ATM機(jī)模擬系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實(shí)現(xiàn)控制臺版本的ATM銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
詳解Spring Security中的HttpBasic登錄驗(yàn)證模式
HttpBasic登錄驗(yàn)證模式是Spring Security實(shí)現(xiàn)登錄驗(yàn)證最簡單的一種方式,也可以說是最簡陋的一種方式,這篇文章主要介紹了Spring Security的HttpBasic登錄驗(yàn)證模式,需要的朋友可以參考下2019-11-11
Java中的關(guān)鍵字synchronized 詳解
這篇文章主要介紹了Java中的關(guān)鍵字synchronized,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03
SpringSecurity實(shí)現(xiàn)前后端分離登錄token認(rèn)證詳解
目前市面上比較流行的權(quán)限框架主要實(shí)Shiro和Spring Security,這兩個框架各自側(cè)重點(diǎn)不同,各有各的優(yōu)劣,本文將給大家詳細(xì)介紹SpringSecurity如何實(shí)現(xiàn)前后端分離登錄token認(rèn)證2023-06-06
解析Java的InputStream類并借助其讀取ppt文件
這篇文章主要介紹了Java的InputStream類并借助其讀取ppt文件,講到了InputStream類中一些常用的方法的問題,需要的朋友可以參考下2015-11-11
feignclient?https?接口調(diào)用報(bào)證書錯誤的解決方案
這篇文章主要介紹了feignclient?https?接口調(diào)用報(bào)證書錯誤的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
mybatis 在typeAliases別名時(shí)報(bào)錯的解決
這篇文章主要介紹了mybatis 在typeAliases別名時(shí)報(bào)錯的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
一文帶你掌握J(rèn)ava?ReentrantLock加解鎖原理
這篇文章將為大家詳細(xì)介紹一下Java中ReentrantLock?加鎖和釋放鎖的原理,以及和?Synchronized?的對比。文中的示例代碼講解詳細(xì),希望對大家有所幫助2022-12-12

