1、官方文档
Spring MVC Auto-configuration
// Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
// 自动配置在Spring默认设置的基础上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
// 包含视图解析器
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
// 支持静态资源文件夹的路径,以及webjars
Support for serving static resources, including support for WebJars
// 自动注册了Converter:
// 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
// Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
Automatic registration of Converter, GenericConverter, and Formatter beans.
// HttpMessageConverters
// SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
Support for HttpMessageConverters (covered later in this document).
// 定义错误代码生成规则的
Automatic registration of MessageCodesResolver (covered later in this document).
// 首页定制
Static index.html support.
// 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
/*
如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
*/
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration
(interceptors, formatters, view controllers, and other features), you can add your own
@Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide
custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or
ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
// 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.
2、ContentNegotiatingViewResolver
内容协商视图解析器
- WebMvcAutoConfiguratio
@Configuration
...
public class WebMvcAutoConfiguration ... {
...
// 内部静态类
@Configuration
...
public static class WebMvcAutoConfigurationAdapter ...{
// 获取视图解析器
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
// 内容协商视图解析器
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver使用所有其他视图解析器来定位视图,因此它应该具有较高的优先级
resolver.setOrder(-2147483648);
return resolver;
}
}
}
- ContentNegotiatingViewResolver
public class ContentNegotiatingViewResolver ... {
...
@Nullable // 参数可以为null
public View resolveViewName(String viewName, Locale locale) throws Exception {
...
// 得到候选视图
List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
// 得到最佳视图
View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
...
}
// 得到候选视图
private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception {
List<View> candidateViews = new ArrayList();
if (this.viewResolvers != null) {
...
// 把所有的视图解析器拿来,进行while循环,挨个解析!
Iterator var5 = this.viewResolvers.iterator();
while(var5.hasNext()) {
...
}
}
...
return candidateViews;
}
}
总结:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
- viewResolvers 属性
public class ContentNegotiatingViewResolver ... {
@Nullable
private List<ViewResolver> viewResolvers;
//setViewResolvers(List<ViewResolver> viewResolvers)
//getViewResolvers()
protected void initServletContext(ServletContext servletContext) {
// 从beanFactory工具中获取容器中的所有视图解析器
// ViewRescolver.class 把所有的视图解析器组合起来
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
Iterator var3 = matchingBeans.iterator();
while(var3.hasNext()) {
viewResolver = (ViewResolver)var3.next();
if (this != viewResolver) {
this.viewResolvers.add(viewResolver);
}
}
} else {
// ...
}
AnnotationAwareOrderComparator.sort(this.viewResolvers);
this.cnmFactoryBean.setServletContext(servletContext);
}
}
- 测试自定义视图解析器
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Bean // 注入spring
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
// 内部静态类:自定义视图解析器
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
在 DispatcherServlet 类中的 doDispatch() 方法上设置断点
Debug启动测试
总结:如果想要使用自己定制化的功能,只需要给容器中添加这个组件就好了!
3、转换器和格式化器
Converter
就是网页提交数据到后台自动封装成为对象的功能,比如把"1"字符串自动转换为int类型
Formatter
如日期格式
4、修改默认配置
- 扩展SpringMVC
添加自己的
@configuration
类,类型为webmvcconfiguer
,但不添加@EnableWebMvc
,如果添加@EnableWebMvc ,自动配置将失效,就不是扩展,而是全面接管自定义配置类是官方推荐的扩展方式
// 应为类型要求为WebMvcConfigurer,所以实现其接口
// 可以使用自定义类扩展MVC的功能
@Configuration
// @EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 浏览器发送/test , 就会跳转到test页面;
registry.addViewController("/test").setViewName("test");
}
}
- 全面接管SpringMVC
就是在自已的配置类中加上
@EnableWebMvc
,让自动配置失效这个注解的意思就是:容器中没有这个组件的时候,这个自动配置类才生效@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
当加上@EnableWebMvc时,容器中就存在了这个组件,自动配置类就不失效
不推荐使用全面接管SpringMVC