SpringBoot源碼學習系列之SpringMVC自動配置

源碼學習系列之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類,翻下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就能自動加載到

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/
  • classpath:/

三、自動註冊 Converter, GenericConverter, and Formatter beans.

在這裏插入圖片描述
翻譯過來就是自動註冊了 Converter, GenericConverter, and Formatter beans.

  • Converter:轉換器 ,做用就是能自動進行類型轉換
    eg: public String hello(User user),這是一個方法,而後前端視圖傳來的參數經過轉換器可以根據屬性進行映射,而後進行屬性類型轉換
  • Formatter :格式化器,eg:好比對前端傳來的日期2019/11/25,進行格式化處理

源碼在這裏,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

HttpMessageConverters :消息轉換器,Springmvc中用來轉換http請求和響應的

源碼裏是經過configureMessageConverters方法實現,很顯然也是從容器裏獲取的
在這裏插入圖片描述

在這裏插入圖片描述
官方文檔裏也進行了比較詳細描述,Springboot已經爲咱們自動配置了json的、xml的自動轉換器,固然你也能夠本身添加
在這裏插入圖片描述

五、支持MessageCodesResolver

在這裏插入圖片描述
MessageCodesResolver:是消息解析器,WebMvcAutoConfiguration.getMessageCodesResolver是實現Exception異常信息格式的
在這裏插入圖片描述
WebMvcProperties配置文件定義的一個異常枚舉值
在這裏插入圖片描述

在這裏插入圖片描述
格式爲如圖所示,定了了錯誤代碼是生成規則:
在這裏插入圖片描述

六、首頁支持

在這裏插入圖片描述
Springboot默認的首頁是index.html,也就是你在classpath路徑丟個index.html文件,就被Springboot默認爲首頁,或者說歡迎頁

如圖示代碼,就是遍歷靜態資源文件,而後獲取index.html做爲歡迎頁面

在這裏插入圖片描述

七、網站logo設置

在這裏插入圖片描述
Springboot1.+版本,是有默認的logo圖標的,2.2.1版本,通過全局搜索,沒有發現給自定義的圖標,使用的話,是直接丟在classpath路徑,文件命名爲favicon.ico,不過在2.2.1代碼並無找到相應的配置代碼,1.+版本是有的,不過文檔仍是有描述了

八、ConfigurableWebBindingInitializer 初始綁定器

在這裏插入圖片描述
跟下源碼,也是從Spring容器裏獲取的,而後注意到,若是沒有這個ConfigurableWebBindingInitializer ,代碼就會調用基類的getConfigurableWebBindingInitializer
在這裏插入圖片描述
源碼,這裏也是建立一個getConfigurableWebBindingInitializer
在這裏插入圖片描述

ConfigurableWebBindingInitializer 是Springboot爲系統自動配置的,固然咱們也能夠本身定義一個ConfigurableWebBindingInitializer ,而後加載到容器裏便可

初始化綁定的方法,ok,本博客簡單跟一下源碼
在這裏插入圖片描述

注意:
ok,Springboot官方文檔裏還有這樣的描述,如圖所示
在這裏插入圖片描述
意思是,在使用webmvcConfigurer配置的時候,不要使用@EnableWebMvc註解,爲何不要使用呢?由於使用了@EnableWebMvc,就是實現全面接管SpringMVC自動配置,也就是說其它的自動配置都會失效,所有本身配置

原理是爲何?能夠簡單跟一下源碼,如圖,SpringMVC自動配置類,有這個很關鍵的註解,這個註解的意思是@WebMvcConfigurationSupport註解不在系統時候自動配置才起效

在這裏插入圖片描述
而後爲何加了@EnableWebMvc自動配置就能夠被全面接管?點一下@EnableWebMvc源碼

在這裏插入圖片描述
很顯然,DelegatingWebMvcConfiguration類extends WebMvcConfigurationSupport類,因此這也就是爲何@EnableWebMvc註解能實現全面接管自動配置的原理在這裏插入圖片描述

相關文章
相關標籤/搜索