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帮助我们进行定制配置
 

 

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