1、官方文档阅读
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
。所以自动配置全部失效了。