目錄html
源碼學習系列之WebMvc自動配置原理筆記前端
@java
web的自動配置在SpringBoot項目中是一個很重要的方面,實現代碼在spring-boot-autoconfigure工程裏:
按照官方文檔的說法,SpringBoot官方的說法,Springboot的SpringMVC自動配置,主要提供了以下自動配置:
web
WebMvcAutoConfiguration.java這個類很關鍵,這個就是SpringBoot Springmvc自動配置的一個很關鍵的配置類spring
@Configuration(proxyBeanMethods = false)//指定WebMvcAutoConfiguration不代理方法 @ConditionalOnWebApplication(type = Type.SERVLET)//在web環境(selvlet)纔會起效 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })//系統有有Servlet,DispatcherServlet(Spring核心的分發器),WebMvcConfigurer的狀況,這個自動配置類才起效 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)//系統沒有WebMvcConfigurationSupport這個類的狀況,自動配置起效 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { .... }
翻下源碼,能夠看到WebMvcAutoConfiguration自動配置類裏還有一個WebMvcConfigurer類型的配置類,2.2.1版本是implements WebMvcConfigurer接口,1.+版本是extends WebMvcConfigurerAdapter
json
@Configuration(proxyBeanMethods = false)//定義爲配置類 @Import(EnableWebMvcConfiguration.class)//spring底層註解,將EnableWebMvcConfiguration加到容器 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })//使WebMvcProperties、ResourceProperties配置類生效 @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { .... }
ok,跟一下WebMvcAutoConfigurationAdapter 裏的關鍵重載方法:緩存
如圖,是視圖解析器的自動配置,這個類起效的狀況是系統沒有ContentNegotiatingViewResolver類的狀況,就調用改方法自動建立ContentNegotiatingViewResolver類
關鍵的是ContentNegotiatingViewResolver類,翻下ContentNegotiatingViewResolver類,找到以下重要的初始化方法mvc
@Override protected void initServletContext(ServletContext servletContext) { //調用Spring的BeanFactoryUtils掃描容器裏的全部視圖解析器ViewResolver類 Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values(); if (this.viewResolvers == null) { this.viewResolvers = new ArrayList<>(matchingBeans.size()); //遍歷候選的viewResolvers,封裝到this.viewResolvers列表 for (ViewResolver viewResolver : matchingBeans) { if (this != viewResolver) { this.viewResolvers.add(viewResolver); } } } else { for (int i = 0; i < this.viewResolvers.size(); i++) { ViewResolver vr = this.viewResolvers.get(i); if (matchingBeans.contains(vr)) { continue; } String name = vr.getClass().getName() + i; obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(vr, name); } } AnnotationAwareOrderComparator.sort(this.viewResolvers); this.cnmFactoryBean.setServletContext(servletContext); }
因此ContentNegotiatingViewResolver類的做用就是組合全部的視圖解析器,自動配置了ViewResolver(視圖解析器做用,根據方法返回值獲得視圖對象view)app
往下翻代碼,能夠看到resolveViewName方法,裏面代碼是從this.viewResolvers獲取候選的視圖解析器,遍歷容器裏全部視圖,而後經過如圖所標記的獲取候選視圖的方法,獲取候選的視圖列表,再經過getBestView獲取最合適的視圖
遍歷全部的視圖解析器對象,從視圖解析器裏獲取候選的視圖,封裝成list保存
ok,跟了源碼就是隻要將視圖解析器丟到Spring容器裏,就能夠加載到框架
寫個簡單的視圖解析類
DispatcherServlet是Spring核心分發器,找到doDispatch方法,debug,能夠看到加的視圖解析器加載到了
也就是官方說的,以下圖所示:
翻譯過來就是支持靜態資源包括webjars的自動配置,webjars,就是以maven等等方式打成jar包的靜態資源,能夠去webjars官網看看文檔:
使用的話,直接去webjars官網負責對應的配置,加到項目裏就能夠
路徑都是在META-INF/webjars/**
WebMvcAutoConfiguration.addResourceHandlers,這個是比較重要的資源配置方法
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); //CacheControl是Spring框架提供的http緩存 CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl(); //讀取到webjars資源,將classpath:/META-INF/resources/webjars/的webjars資源都掃描出來 if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/") .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } }
ok,經過源碼能夠知道,Springboot支持webjars和其它等等靜態資源,其它的靜態資源要放在以下目錄裏,Springboot就能自動加載到
翻譯過來就是自動註冊了 Converter, GenericConverter, and Formatter beans.
源碼在這裏,WebMvcAutoConfiguration.addFormatters方法是添加格式化器的方法
同理,也是從Spring容器裏將這幾種類拿過來
固然,還有其它的,好比WebMvcAutoConfiguration.localeResolver方法是實現i18n國際化語言支持的自動配置
@Bean @ConditionalOnMissingBean//沒有自定義localeResolver的狀況 @ConditionalOnProperty(prefix = "spring.mvc", name = "locale")//application.properties有配置了spring.mvc.locale public LocaleResolver localeResolver() { if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } //默認使用AcceptHeaderLocaleResolver AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); return localeResolver; }
具體的源碼參考我以前博客:SpringBoot系列之i18n國際化多語言支持教程,博客裏面有涉及源碼的
HttpMessageConverters :消息轉換器,Springmvc中用來轉換http請求和響應的
源碼裏是經過configureMessageConverters方法實現,很顯然也是從容器裏獲取的
官方文檔裏也進行了比較詳細描述,Springboot已經爲咱們自動配置了json的、xml的自動轉換器,固然你也能夠本身添加
MessageCodesResolver:是消息解析器,WebMvcAutoConfiguration.getMessageCodesResolver是實現Exception異常信息格式的
WebMvcProperties配置文件定義的一個異常枚舉值
格式爲如圖所示,定了了錯誤代碼是生成規則:
Springboot默認的首頁是index.html,也就是你在classpath路徑丟個index.html文件,就被Springboot默認爲首頁,或者說歡迎頁
如圖示代碼,就是遍歷靜態資源文件,而後獲取index.html做爲歡迎頁面
Springboot1.+版本,是有默認的logo圖標的,2.2.1版本,通過全局搜索,沒有發現給自定義的圖標,使用的話,是直接丟在classpath路徑,文件命名爲favicon.ico,不過在2.2.1代碼並無找到相應的配置代碼,1.+版本是有的,不過文檔仍是有描述了
跟下源碼,也是從Spring容器裏獲取的,而後注意到,若是沒有這個ConfigurableWebBindingInitializer ,代碼就會調用基類的getConfigurableWebBindingInitializer
源碼,這裏也是建立一個getConfigurableWebBindingInitializer
ConfigurableWebBindingInitializer 是Springboot爲系統自動配置的,固然咱們也能夠本身定義一個ConfigurableWebBindingInitializer ,而後加載到容器裏便可
初始化綁定的方法,ok,本博客簡單跟一下源碼
注意:
ok,Springboot官方文檔裏還有這樣的描述,如圖所示
意思是,在使用webmvcConfigurer配置的時候,不要使用@EnableWebMvc註解,爲何不要使用呢?由於使用了@EnableWebMvc,就是實現全面接管SpringMVC自動配置,也就是說其它的自動配置都會失效,所有本身配置
原理是爲何?能夠簡單跟一下源碼,如圖,SpringMVC自動配置類,有這個很關鍵的註解,這個註解的意思是@WebMvcConfigurationSupport註解不在系統時候自動配置才起效
而後爲何加了@EnableWebMvc自動配置就能夠被全面接管?點一下@EnableWebMvc源碼
很顯然,DelegatingWebMvcConfiguration類extends WebMvcConfigurationSupport類,因此這也就是爲何@EnableWebMvc註解能實現全面接管自動配置的原理