Spring Boot为Spring MVC提供了自动配置,适用于大多数应用程序,源码主要在WebMvcAutoConfiguration类里面,我们结合文档来了解一下MVC的自动配置
文档地址:Springboot参考指南
自动配置在Spring的默认值之上添加了以下功能(WebMvcAutoConfiguration
):
包含ContentNegotiatingViewResolver
和BeanNameViewResolver
beans。
1.自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
2.ContentNegotiatingViewResolver:组合所有的视图解析器的;
3.如何定制:我们可以自己给容器中添加一个视图解析器ViewResolver;自动的将其组合进来;
支持提供静态资源,包括对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;
如果你想保留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;
}
如果您想完全控制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最基本的功能;
模式:
1)、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;(理解成同一个系统WebMvcConfigurer)
2)、在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置,多个xxxConfigurer,全部会扫描进来
3)、在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置