天天看點

springboot之mvc自動裝配

官網閱讀

在進行項目編寫前,我們還需要知道一個東西,就是SpringBoot對我們的SpringMVC還做了哪些配置,包括如何擴充,如何定制。

隻有把這些都搞清楚了,我們在之後使用才會更加得心應手。途徑一:源碼分析,途徑二:官方文檔!

Spring MVC Auto-configuration// Spring Boot為Spring MVC提供了自動配置,它可以很好地與大多數應用程式一起工作。Spring Boot provides auto-configuration for Spring MVC that works well with most applications.// 自動配置在Spring預設設定的基礎上添加了以下功能:The auto-configuration adds the following features on top of Spring’s defaults:// 包含視圖解析器Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.// 支援靜态資源檔案夾的路徑,以及webjarsSupport for serving static resources, including support for WebJars // 自動注冊了Converter:// 轉換器,這就是我們網頁送出資料到背景自動封裝成為對象的東西,比如把"1"字元串自動轉換為int類型// Formatter:【格式化器,比如頁面給我們了一個2019-8-10,它會給我們自動格式化為Date對象】Automatic registration of Converter, GenericConverter, and Formatter beans.// HttpMessageConverters// SpringMVC用來轉換Http請求和響應的的,比如我們要把一個User對象轉換為JSON字元串,可以去看官網文檔解釋;Support for HttpMessageConverters (covered later in this document).// 定義錯誤代碼生成規則的Automatic registration of MessageCodesResolver (covered later in this document).// 首頁定制Static index.html support.// 圖示定制Custom Favicon support (covered later in this document).// 初始化資料綁定器:幫我們把請求資料綁定到JavaBean中!Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
/*如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(攔截器、格式化程式、視圖控制器和其他功能),則可以添加自己的@configuration類,類型為webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定義執行個體,則可以聲明WebMVCregistrationAdapter執行個體來提供此類元件。*/If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
// 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc進行注釋。If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.      

我們來仔細對照,看一下它怎麼實作的,它告訴我們SpringBoot已經幫我們自動配置好了SpringMVC,然後自動配置了哪些東西呢?

ContentNegotiatingViewResolver 内容協商視圖解析器

自動配置了ViewResolver,就是我們之前學習的SpringMVC的視圖解析器;

即根據方法的傳回值取得視圖對象(View),然後由視圖對象決定如何渲染(轉發,重定向)。

我們去看看這裡的源碼:我們找到 WebMvcAutoConfiguration , 然後搜尋ContentNegotiatingViewResolver。找到如下方法!

@Bean@ConditionalOnBean(ViewResolver.class)@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();    resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));    // ContentNegotiatingViewResolver使用所有其他視圖解析器來定位視圖,是以它應該具有較高的優先級    resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);    return resolver;}      

我們可以點進這類看看!找到對應的解析視圖的代碼;

@Nullable // 注解說明:@Nullable 即參數可為nullpublic View resolveViewName(String viewName, Locale locale) throws Exception {  
  RequestAttributes attrs = RequestContextHolder.getRequestAttributes();    Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");  
  List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());    if (requestedMediaTypes != null) {     
// 擷取候選的視圖對象        List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);        // 選擇一個最适合的視圖對象,然後把這個對象傳回    
    View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);      
if (bestView != null) {            return bestView;        }   
 }    // .....}      

我們繼續點進去看,他是怎麼獲得候選的視圖的呢?

getCandidateViews中看到他是把所有的視圖解析器拿來,進行while循環,挨個解析!

Iterator var5 = this.viewResolvers.iterator();      

是以得出結論:ContentNegotiatingViewResolver 這個視圖解析器就是用來組合所有的視圖解析器的

我們再去研究下他的組合邏輯,看到有個屬性viewResolvers,看看它是在哪裡進行指派的!

protected void initServletContext(ServletContext servletContext) {    
// 這裡它是從beanFactory工具中擷取容器中的所有視圖解析器    // ViewRescolver.class 把所有的視圖解析器來組合的    
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();   
 ViewResolver viewResolver;    if (this.viewResolvers == null) {        this.viewResolvers = new ArrayList(matchingBeans.size());  
  }    // ...............}      

既然它是在容器中去找視圖解析器,我們是否可以猜想,我們就可以去實作一個視圖解析器了呢?

我們可以自己給容器中去添加一個視圖解析器;這個類就會幫我們自動的将它組合進來;我們去實作一下

springboot之mvc自動裝配

 ps:為什麼添加@EnableWebMvc注解後自動配置的mvc失效

檢視@EnableWebMvc注解

 發現導入一個類

springboot之mvc自動裝配

檢視發現繼承WebMvcConfigurationSupport類

springboot之mvc自動裝配

 而檢視WebMvc自動配置類發現當存在WebMvcConfigurationSupport類時自動配置失效

springboot之mvc自動裝配