[SpringBoot-09]源码解析SpringBoot中MVC的自动配置原理

1、官方文档阅读

  地址:https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration
在这里插入图片描述
  翻译过来就是:

Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
自动配置在Spring默认设置的基础上添加了以下功能:
	包含视图解析器
	支持静态资源文件夹的路径,以及webjars
	自动注册了:
		Converter:就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
		Formatter:比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象
	支持HttpMessageConverters:SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
	定义错误代码生成规则
	首页定制
	图标定制
	初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!

如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。

如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。

  也就是说,如果我们要定制自己的MVC配置,只需要继承WebMvcConfigurer接口,并用@Configuration注解,然后重写对应的方法即可。如果加上了@EnableWebMvc注解,就说明不是部分修改配置,而是全部修改了。
在这里插入图片描述
  阅读这段源码,其实已经知道SpringBoot自动配置了哪些东西。

2、源码解析

  上面是官网描述,接下来我们源码进行分析。
  首先还是找到自动配置类WebMvcAutoConfiguration
在这里插入图片描述

2.1 ContentNegotiatingViewResolver

  即内容协商视图解析器,就是之前学SpringMVC的视图解析器。它根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。我们从这个自动配置类找到如下方法:

@Bean
@ConditionalOnBean({ViewResolver.class})
@ConditionalOnMissingBean(
	name = {"viewResolver"},
	value = {ContentNegotiatingViewResolver.class}
)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
	ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
	resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
	resolver.setOrder(-2147483648);
	return resolver;
}

  这个方法返回的就是ContentNegotiatingViewResolver对象,我继续看这个类,找到对应的解析视图的代码:
在这里插入图片描述
  点进去这个方法getCandidateViews看它是如何获得候选的视图:
在这里插入图片描述
  原来是把所有的视图解析器都拿来遍历,挨个解析。所以ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的。
  然后看到类ContentNegotiatingViewResolver里面有个initServletContext方法
在这里插入图片描述
  这里就得出一个重大结论:既然它是从容器中找视图解析器,那我们直接写一个视图解析器放到容器中,这个ContentNegotiatingViewResolver就会自动把它组合起来。
  下面来试一下自定义视图解析器,看SpringBoot能不能加载进来。

package cn.klb.springboot_helloworld.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Locale;

/**
 * @Author: Konglibin
 * @Description:
 * @Date: Create in 2020/4/25 17:56
 * @Modified By:
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Bean
    public ViewResolver myViewResolver(){
        return new MyViewResolver();
    }

    private static class MyViewResolver implements ViewResolver{
        @Override
        public View resolveViewName(String s, Locale locale) throws Exception {
            return null;
        }
    }
}

  然后在类DispatcherServlet这里打个断点:
在这里插入图片描述
  结果:
在这里插入图片描述
  因此,如果需要自己定制东西,只需要给容器中添加这个组件即可。

2.2 转换器和格式化器

  继续分析类WebMvcAutoConfiguration,找到格式化器方法:

@Bean
public FormattingConversionService mvcConversionService() {
	WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
	this.addFormatters(conversionService);
	return conversionService;
}

  它调用了this.mvcProperties.getDateFormat()方法,点进去:

public String getDateFormat() {
	return this.dateFormat;
}

  就从WebMvcProperties中找到上面这个方法,也就是说我们可以从配置文件中配置它。

2.3 小结

  SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;
  如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
  我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer(即实现这个接口),还不能标注@EnableWebMvc注解;我们去自己写一个;我们新建一个包叫config,写一个类MyMvcConfig;

package cn.klb.springboot_helloworld.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


/**
 * @Author: Konglibin
 * @Description:
 * @Date: Create in 2020/4/25 17:56
 * @Modified By:
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    	// 浏览器发送/order, 就会跳转到order页面;
        registry.addViewController("/order").setViewName("order");
    }
}

  写一个order.html:
在这里插入图片描述
  测试:
在这里插入图片描述
  所以得出结论:所有的WebMvcConfiguration都会起作用,不止Spring自己的配置类,我们自己的配置类当然也会被调用;

3、全面接管SpringMVC

  上面已经说过如果自己定义的MVC配置类使用了@EnableWebMvc注解,那么自动配置全部失效,我们自己配置的会生效。
  我们可以看一下这个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

  点进去这个DelegatingWebMvcConfiguration
在这里插入图片描述
  它继承了WebMvcConfigurationSupport,于是我回到WebMVC的自动配置类:
在这里插入图片描述
  这里就清楚的写明,当没有WebMvcConfigurationSupport时,自动配置才会生效。如果我们使用了@EnableWebMvc注解,也就有了WebMvcConfigurationSupport。所以自动配置全部失效了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值