Spring Boot 之 SpringMVC 自動配置原理 version 1.5.9

一、相關文檔查看

近日閱讀了SpringMVC自動配置的源碼,總結一下

https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

二、理解解析

以下是Spring Boot對Spring MVC的默認配置(WebMvcAutoConfiguration)

配置文件的位置 ~ 在Spring Boot原理哪一篇知道,Spring Boot對很多框架的支持配置文件命名爲: xxxAutoConfiguration

1、包含了ContentNegotiatingViewResolver  和 BeanNameViewResolver 

1.1 ContentNegotiatingViewResolver 

自動轉配了該類,查看ContentNegotiatingViewResolver

【總結來說】自動配置了ViewResolver(視圖解析器),視圖解析器就是根據方法的返回值得到視圖對象View,視圖對象將決定如何渲染...

ContentNegotiatingViewResolver 組合了所有的視圖

那麼問題來了,我們如何定義我們自己的視圖呢?自動將其組合進來

1)寫一個類實現ViewResolver接口,然後實現裏面的resolveViewName方法

2)生成改Bean,交給Spring管理

@Component
public class TestViewResolver implements ViewResolver {
    @Override
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        return null;
    }
}

重新啓動項目

【再次總結】

1、Spring Boot在自動配置很多組件的時候,先看容器有沒有用戶配置的(@Bean/@Component),如果有,就用用戶自己配置的,如果沒有,才自動配置。

但是有些組件可以有多個,例如ViewResolver將用戶的配置和自己的默認組合起來

1.2 BeanNameViewResolver 解析器試圖將返回的名稱當作視圖bean的name

 

2、靜態資源文件夾路徑 webjars

對公共靜態資源的訪問時,支持使用webjar去訪問到jaj包裏面的靜態文件,例如

1)在Pom文件中引入jq.jar

  <!--引入jQuery-webjar-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.1</version>
        </dependency>

2) 項目啓動之後,訪問:

http://localhost:8081/webjars/jquery/3.1.1/jquery.js

3、自動註冊了Converter、GenericConverter、formatter beans

converter: 轉化器,類型轉化使用Converter

Formatter: 格式轉化器, 2020.06.03 ===》 Date

以Formatter分析

查看this.mvcProperties

【總結兩個點】

1)默認情況下,使用/來解析日期

2)如果想要自己添加格式化轉化器,我們只需要放在容器中即可。

3)自定義自己的日期轉化器

@Component
public class MyDateConverter implements Converter<String, Date> {
    private String dataPattern = "yyyy-MM-dd";

    @Override
    public Date convert(String s) {
        Date date = null;
        try {
            date = new SimpleDateFormat(dataPattern).parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;

    }
}

4)重新啓動項目

【注意】日期格式化只能支持一種,此時如果使用:1995/08/10則報錯

4、支持HttpMessageConverters

     SpringMvc用來轉化Http請求和響應, User-- JSON

      HttpMessageConverters是從容器中確定的,獲取所有的httpMessageConverter

那麼如何給容器中添加HttpMessageConverter,只需要將自己的組件註冊進容器中即可

5、定義錯誤代碼生成規則 MessageCodesResolver 

目錄

一、相關文檔查看

二、理解解析

1、包含了ContentNegotiatingViewResolver  和 BeanNameViewResolver 

2、靜態資源文件夾路徑 webjars

3、自動註冊了Converter、GenericConverter、formatter beans

4、支持HttpMessageConverters

5、定義錯誤代碼生成規則 MessageCodesResolver 

​6、 靜態首頁資源配置

7、默認的圖標 

8、配置默認的ConfigurableWebBindingInitializer 來替換默認的

三、添加額外的MVC配置

原理

四、全面接管SpringMVC

原理:

五、如何修改SpringBoot的默認配置

模式:


6、 靜態首頁資源配置

將"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"

四個位置存在的index.html當做首頁,如果不存在則報錯。並且優先級由高到底

7、默認的圖標 

因此,只需要將圖標放在靜態資源路徑下,命名爲:favicon.ico,則可以更換圖標

8、配置默認的ConfigurableWebBindingInitializer 來替換默認的

三、添加額外的MVC配置

如果想要保持原來的自動配置不變,增加自己的配置,則可以

1)添加一個類使用@Configuration

2)繼承WebMvcConfigurerAdapter

package com.dgut.edu.cn.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Locale;


@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    private String dataPattern = "yyyy=MM=dd";
    public MyMvcConfig() {
        super();
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        super.configureContentNegotiation(configurer);
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        super.configureAsyncSupport(configurer);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        super.configureDefaultServletHandling(configurer);
    }

    @Override
        public void addFormatters(FormatterRegistry registry) {

        registry.addFormatter(new Formatter<Date>() {
            @Override
            public String print(Date date, Locale locale) {
                return Long.valueOf(date.getTime()).toString();
            }

            @Override
            public Date parse(String s, Locale locale) throws ParseException {
                Date date = null;
                try {
                    date = new SimpleDateFormat(dataPattern).parse(s);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return date;
            }
        });

        super.addFormatters(registry);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        super.addResourceHandlers(registry);
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        super.addCorsMappings(registry);
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //super.addViewControllers(registry);
        registry.addViewController("/atguigu").setViewName("success");
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        super.configureViewResolvers(registry);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
        super.addReturnValueHandlers(returnValueHandlers);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.extendMessageConverters(converters);
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        super.configureHandlerExceptionResolvers(exceptionResolvers);
    }

    @Override
    public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        super.extendHandlerExceptionResolvers(exceptionResolvers);
    }

    @Override
    public Validator getValidator() {
        return super.getValidator();
    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return super.getMessageCodesResolver();
    }
}

此時,新增加的視圖映射也會實現

原理

1)WebMvcAutoConfiguration是SpringMVC的自動配置類

2)在做其他自動配置時會導入;@Import(EnableWebMvcConfiguration.class)

 

由於:WebMvcConfigureAdapter 實現WebMvcConfigurer,因此我們的類也會被加載

 

3)容器中所有的WebMvcConfigurer都會一起起作用
4)我們的配置類也會被調用;

【總結】

SpringMVC的自動配置和我們的擴展配置都會起作用


四、全面接管SpringMVC

我們需要在配置類中添加@EnableWebMvc

 

因此全面交由自己管理SpringMvc,但是在項目中不推薦使用

原理:

爲什麼增加了該註解,自動配置就失效了呢?

1、查看該註解

使用該註解時,導入了 

DelegatingWebMvcConfiguration.class

2、查看SpringMvc生效的條件

 

五、如何修改SpringBoot的默認配置


模式:


1)、SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component)如
果有就用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(ViewResolver)將用戶配置的和自己默
認的組合起來;
2)、在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
3)、在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章