SpringBoot2--SpringMVC自动配置

前言

Spring Boot为Spring MVC提供了自动配置,适用于大多数应用程序,源码主要在WebMvcAutoConfiguration类里面,我们结合文档来了解一下MVC的自动配置

一、Spring MVC auto-configuration

文档地址:Springboot参考指南
自动配置在Spring的默认值之上添加了以下功能(WebMvcAutoConfiguration):

  • 包含ContentNegotiatingViewResolverBeanNameViewResolver beans。

    1.自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
    2.ContentNegotiatingViewResolver:组合所有的视图解析器的;
    3.如何定制:我们可以自己给容器中添加一个视图解析器ViewResolver;自动的将其组合进来;
    SpringBoot2--SpringMVC自动配置_第1张图片

  • 支持提供静态资源,包括对WebJars的支持。

  • 静态index.html支持。

  • 自定义Favicon支持(本文档稍后介绍)。

  • 自动注册Converter,GenericConverter和Formatter beans。
    1.Converter(转换器):将页面提交的数据转换为后台接受的数据(如页面提交用户的年龄,性别信息,后台用User对象接收,使用Converter做类型转换)
    2.Formatter 格式化器; 2017.12.17===Date;自己添加的格式化器转换器

  	@Bean
  	@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在文件中配置日期格式化的规则
  	public Formatter<Date> dateFormatter() {
  		return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
  	}

自己添加的Formatter 格式化器、Converter 转换器,我们只需要放在容器中即可

  • 支持HttpMessageConverters( )。
    1.HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User—Json;
    2.HttpMessageConverters 是从容器中确定;获取所有的HttpMessageConverter;
    自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)

  • 自动注册MessageCodesResolver
    生成错误代码的策略,用于从绑定错误中呈现错误消息

  • 自动使用ConfigurableWebBindingInitializer bean(本文 后面会介绍)。
    我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)
    功能:初始化WebDataBinder;请求数据=====JavaBean;

二、扩展SpringMVC配置

如果你想保留Spring Boot MVC功能,并且你想添加额外的 MVC配置(拦截器,格式化程序,视图控制器和其他功能)编写一个配置类(@Configuration),这个类是WebMvcConfigurer(实现这个接口)类型的;不能标注@EnableWebMvc;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

	public void addViewControllers(ViewControllerRegistry registry) {
		//发送 /cheng请求来到"success"页面
		registry.addViewController("/cheng").setViewName("success");

	}

原理:

​ 1)、WebMvcAutoConfiguration是SpringMVC的自动配置类

​ 2)、在做其他自动配置时会导入;@Import(EnableWebMvcConfiguration.class)


@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

   //从容器中获取所有的WebMvcConfigurer
    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
            //一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;  
            	@Override
             // public void addViewControllers(ViewControllerRegistry registry) {
              //    for (WebMvcConfigurer delegate : this.delegates) {
               //       delegate.addViewControllers(registry);
               //   }
        }

    }

3)、容器中所有的WebMvcConfigurer都会一起起作用;我们的配置类也会被调用;
​ 效果:SpringMVC的自动配置和我们的扩展配置都会起作用;
4)、依据这个原理也可以在配置类里面定义一个返回WebMvcConfigurer类的方法,并标注@Bean,那么这个方法的返回值会自动添加到容器

    //定义一个@Bean类,返回值是WebMvcConfigurer
    @Bean//将组件注册到容器
	public WebMvcConfigurer webMvcConfigurer(){
		WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer(){

			//解析器
			@Override
			public void addViewControllers(ViewControllerRegistry registry) {
				registry.addViewController("/").setViewName("login");
				registry.addViewController("/index.html").setViewName("login");
				registry.addViewController("/main.html").setViewName("dashboard");
			}
            //注册拦截器
			//双重功能:1.session  2.拦截转发
			public void addInterceptors(InterceptorRegistry registry) {
				registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
						.excludePathPatterns("/index.html","/","/user/login","/asserts/**","/webjars/**");

			}
		};

		return webMvcConfigurer;
	}

三、全面接管SpringMVC配置

如果您想完全控制Spring MVC,可以添加自己的@Configuration注释@EnableWebMvc。SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己配置;所有的SpringMVC的自动配置都失效了
我们需要在配置类中添加@EnableWebMvc即可;

@EnableWebMvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

	public void addViewControllers(ViewControllerRegistry registry) {
		//发送 /cheng请求来到"success"页面
		registry.addViewController("/cheng").setViewName("success");

	}

原理: 为什么@EnableWebMvc自动配置就失效了;
1)@EnableWebMvc的核心

@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

2)DelegatingWebMvcConfiguration

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

3)WebMvcAutoConfiguration
SpringMVC的自动配置类WebMvcAutoConfiguration的头上有个
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)注解,当容器中没有WebMvcConfigurationSupport这个类时,这个自动配置类才会生效,所以自动配置类会失效

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

4)@EnableWebMvc将WebMvcConfigurationSupport组件导入进来,所以WebMvcAutoConfiguration不会生效

5)导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能;

四、如何修改SpringBoot的默认配置

模式:

​ 1)、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;(理解成同一个系统WebMvcConfigurer)
2)、在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置,多个xxxConfigurer,全部会扫描进来
3)、在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置

你可能感兴趣的:(Springboot)