1. 程式人生 > >SpringBoot原始碼學習系列之SpringMVC自動配置

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

目錄

  • 1、ContentNegotiatingViewResolver
  • 2、靜態資源
  • 3、自動註冊 Converter, GenericConverter, and Formatter beans.
  • 4、支援HttpMessageConverters
  • 5、支援MessageCodesResolver
  • 6、首頁支援
  • 7、網站logo設定
  • 8、ConfigurableWebBindingInitializer 初始繫結器

原始碼學習系列之WebMvc自動配置原理筆記

@

web的自動配置在SpringBoot專案中是一個很重要的方面,實現程式碼在spring-boot-autoconfigure工程裡:

按照官方文件的說法,SpringBoot官方的說法,Springboot的SpringMVC自動配置,主要提供瞭如下自動配置:

WebMvcAutoConfiguration.java這個類很關鍵,這個就是SpringBoot Springmvc自動配置的一個很關鍵的配置類

@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

@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 裡的關鍵過載方法:

1、ContentNegotiatingViewResolver


如圖,是檢視解析器的自動配置,這個類起效的情況是系統沒有ContentNegotiatingViewResolver類的情況,就呼叫改方法自動建立ContentNegotiatingViewResolver類

關鍵的是ContentNegotiatingViewResolver類,翻下ContentNegotiatingViewResolver類,找到如下重要的初始化方法

@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)

往下翻程式碼,可以看到resolveViewName方法,裡面程式碼是從this.viewResolvers獲取候選的檢視解析器,遍歷容器裡所有檢視,然後通過如圖所標記的獲取候選檢視的方法,獲取候選的檢視列表,再通過getBestView獲取最合適的檢視

遍歷所有的檢視解析器物件,從檢視解析器裡獲取候選的檢視,封裝成list儲存

ok,跟了原始碼就是隻要將檢視解析器丟到Spring容器裡,就可以載入到

寫個簡單的檢視解析類

DispatcherServlet是Spring核心分發器,找到doDispatch方法,debug,可以看到加的檢視解析器載入到了

2、靜態資源

也就是官方說的,如下圖所示:

翻譯過來就是支援靜態資源包括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:/

3、自動註冊 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國際化多語言支援教程,部落格裡面有涉及原始碼的

4、支援HttpMessageConverters

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

原始碼裡是通過configureMessageConverters方法實現,很顯然也是從容器裡獲取的


官方文件裡也進行了比較詳細描述,Springboot已經為我們自動配置了json的、xml的自動轉換器,當然你也可以自己新增

5、支援MessageCodesResolver


MessageCodesResolver:是訊息解析器,WebMvcAutoConfiguration.getMessageCodesResolver是實現Exception異常資訊格式的

WebMvcProperties配置檔案定義的一個異常列舉值


格式為如圖所示,定了了錯誤程式碼是生成規則:

6、首頁支援


Springboot預設的首頁是index.html,也就是你在classpath路徑丟個index.html檔案,就被Springboot預設為首頁,或者說歡迎頁

如圖示程式碼,就是遍歷靜態資原始檔,然後獲取index.html作為歡迎頁面

7、網站logo設定


Springboot1.+版本,是有預設的logo圖示的,2.2.1版本,經過全域性搜尋,沒有發現給自定義的圖示,使用的話,是直接丟在classpath路徑,檔案命名為favicon.ico,不過在2.2.1程式碼並沒有找到相應的配置程式碼,1.+版本是有的,不過文件還是有描述了

8、ConfigurableWebBindingInitializer 初始繫結器


跟下原始碼,也是從Spring容器裡獲取的,然後注意到,如果沒有這個ConfigurableWebBindingInitializer ,程式碼就會呼叫基類的getConfigurableWebBindingInitializer

原始碼,這裡也是建立一個getConfigurableWebBindingInitializer

ConfigurableWebBindingInitializer 是Springboot為系統自動配置的,當然我們也可以自己定義一個ConfigurableWebBindingInitializer ,然後載入到容器裡即可

初始化繫結的方法,ok,本部落格簡單跟一下原始碼

注意:
ok,Springboot官方文件裡還有這樣的描述,如圖所示

意思是,在使用webmvcConfigurer配置的時候,不要使用@EnableWebMvc註解,為什麼不要使用呢?因為使用了@EnableWebMvc,就是實現全面接管SpringMVC自動配置,也就是說其它的自動配置都會失效,全部自己配置

原理是為什麼?可以簡單跟一下原始碼,如圖,SpringMVC自動配置類,有這個很關鍵的註解,這個註解的意思是@WebMvcConfigurationSupport註解不在系統時候自動配置才起效


然後為什麼加了@EnableWebMvc自動配置就可以被全面接管?點一下@EnableWebMvc原始碼


很顯然,DelegatingWebMvcConfiguration類extends WebMvcConfigurationSupport類,所以這也就是為什麼@EnableWebMvc註解能實現全面接管自動配置的原理

相關推薦

SpringBoot原始碼學習系列SpringMVC自動配置

目錄 1、ContentNegotiatingViewResolver 2、靜態資源 3、自動註冊 Converter, GenericConverter, and Formatter beans. 4、支援

springboot學習筆記SpringMVC自動配置原理

Springboot中自動配置Springmvc的檔案 @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, D

SpringBoot原始碼學習系列嵌入式Servlet容器

目錄 1、部落格前言簡單介紹 2、定製servlet容器 3、變換servlet容器 4、servlet容器啟動原理 SpringBoot原始碼學習系列之嵌入式Servlet容器

SpringBoot原始碼學習系列啟動原理簡介

本部落格通過debug方式簡單跟一下Springboot application啟動的原始碼,Springboot的啟動原始碼是比較複雜的,本部落格只是簡單梳理一下原始碼,淺析其原理 為了方便跟原始碼,先找個Application類,打個斷點,進行除錯,如圖所示: step into,run方法呼叫了Sp

原始碼學習系列SpringBoot自動配置(篇一)

原始碼學習系列之SpringBoot自動配置原始碼學習(篇一) ok,本部落格嘗試跟一下Springboot的自動配置原始碼,做一下筆記記錄,自動配置是Springboot的一個很關鍵的特性,也容易被忽略的屬性,因為這個屬性被包括在@SpringBootApplication註解裡,所以不去跟一下原始碼都不知

原始碼學習系列SpringBoot自動配置(篇二)

原始碼學習系列之SpringBoot自動配置(篇二)之HttpEncodingAutoConfiguration 原始碼分析 繼上一篇部落格原始碼學習系列之SpringBoot自動配置(篇一)之後,本部落格繼續跟一下SpringBoot的自動配置原始碼 ok,先複習一下上一篇的內容,從前面的學習,我們知道了S

SpringBoot——web開發SpringMVC自動配置原理

一、SpringBoot為SpringMVC提供的自動配置 2、SpringBoot為SpringMVC提供的自動配置:參考類WebMvcAutoConfiguration ①Inclusion of ContentNegotiatingViewResolver an

springboot初級學習系列十解決@Entity不能自動生成對應表問題(已解決)

在實體類上加@Entity就會對應生成相應的表,可是有時卻怎麼也生不成解決方法:1、檢查啟動類是否配有:@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoC

ClickHouse學習系列三【配置檔案說明】

背景       最近花了些時間看了下ClickHouse文件,發現它在OLAP方面表現很優異,而且相對也比較輕量和簡單,所以準備入門瞭解下該資料庫系統。在介紹了安裝和使用者許可權管理之後,本文對其配置檔案做下相關的介紹說明。 說明       Cl

Netty原始碼學習系列1-NioEventLoopGroup的初始化

前言     NioEventLoopGroup是netty對Reactor執行緒組這個抽象概念的具體實現,其內部維護了一個EventExecutor陣列,而NioEventLoop就是EventExecutor的實現(看名字也可發現,一個是NioEventLoopGroup,一個是Nio

Netty原始碼學習系列2-ServerBootstrap的初始化

前言     根據前文我們知道,NioEventLoopGroup和NioEventLoop是netty對Reactor執行緒模型的實現,而本文要說的ServerBootstrap是對上面二者的整合與呼叫,是一個統籌者和協調者。具體netty使用的是Reactor單執行緒模型還是多執行緒模

Netty原始碼學習系列4-ServerBootstrap的bind方法

前言     今天研究ServerBootstrap的bind方法,該方法可以說是netty的重中之重、核心中的核心。前兩節的NioEventLoopGroup和ServerBootstrap的初始化就是為bind做準備。照例貼上一下這個三朝元老的demo,開始本文內容。 1 publ

Netty原始碼學習系列5-NioEventLoop的run方法

前言     NioEventLoop的run方法,是netty中最核心的方法,沒有之一。在該方法中,完成了對已註冊的channel上來自底層作業系統的socket事件的處理(在服務端時事件包括客戶端的連線事件和讀寫事件,在客戶端時是讀寫事件)、單執行緒任務佇列的處理(服務端的註冊事件、客

Spring5.0原始碼學習系列淺談BeanFactory建立

Spring5.0原始碼學習系列之淺談BeanFactory建立過程 # 系列文章目錄 提示:[Spring原始碼學習專欄連結](https://blog.csdn.net/u014427391/category_10493299.html) # 部落格前言介紹 提示:在[上一章](https://s

Spring5.0原始碼學習系列淺談迴圈依賴問題

## 前言介紹 附錄:[Spring原始碼學習專欄](https://blog.csdn.net/u014427391/category_10493299.html) 在[上一章](https://blog.csdn.net/u014427391/article/details/109625421)的學習中

Spring5.0原始碼學習系列Spring AOP簡述

## 前言介紹 附錄:[Spring原始碼學習專欄](https://blog.csdn.net/u014427391/category_10493299.html) 在前面章節的學習中,我們對Spring框架的IOC實現原始碼有了一定的瞭解,接著本文繼續學習Springframework一個核心的技術

SpringBoot原始碼學習路(七、SpringBoot中對SpringMVC自動配置

SpringMVC自動配置 一. Spring MVC auto-configuration 對於SpringMVC的自動配置下面只是介紹了部分,如果想要了解更多Boot對SpringMVC的預設配置可以查閱原始碼結合官方文件瞭解。 原始

SpringBoot學習路】12.SpringMVC自動配置詳解

轉載宣告:商業轉載請聯絡作者獲得授權,非商業轉載請註明出處.原文來自 © 呆萌鍾【SpringBoot學習之路】12.SpringMVC自動配置詳解  SpringMVC自動配置 Spring MVC auto-configuration Sprin

SpringBoot學習-SpringMVC自動配置

SpringBoot學習-SpringMVC自動配置   前言 在SpringBoot官網對於SpringMVCde 自動配置介紹 1-原文介紹如下: Spring MVC Auto-configuration Spring Boot provides auto-configuratio

SpringBoot-Mybatis_Plus學習記錄公共字段自動填充

ast 使用配置 後臺 pri emp port 更多 但是 pub 一.應用場景 平時在建對象表的時候都會有最後修改時間,最後修改人這兩個字段,對於這些大部分表都有的字段,每次在新增和修改的時候都要考慮到這幾個字段有沒有傳進去,很麻煩。mybatisPlus有一個很