学习springMVC时最佳方式就是看着官方文档学习。
网址为:https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#boot-features-developing-web-applications
了解它spring web mvc 的框架的特性
那么从4.7.1. The “Spring Web MVC Framework”章节开始
它说The Spring Web MVC framework (often referred to as simply “Spring MVC”)
springMVC的灵魂就在@Controller和@RestController,还举例说明如何使用。。。
闲话不说太多。好了,接下来进入正题:Spring MVC Auto-configuration
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.
// 图标定制
Custom Favicon support (covered later in this document).
// 初始化数据绑定器:帮我们把请求数据绑定到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.
8个特性,举例进行学习即可,
1.包含了ContentNegotiatingViewResolver 和BeanNameViewResolver 的beans
也就是自带了视图解析器的意思。
我shift+shift,查找了ContentNegotiatingViewResolver 这个类
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
implements ViewResolver, Ordered, InitializingBean {
}
实现了ViewResolver接口,这个接口是这样的:
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
那么说是不是实现了这个接口就是视图解析器呢?
在下面有这样一句话:如果您想保留这些Spring Boot MVC定制并进行更多MVC定制(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己的WebMVCConfiguer类型的@Configuration类,但不要添加@EnableWebMvc。
我创建一个类进行测试:
@Configuration
public class MyMVCConfig {
//所有的请求都会经过dispatcherServlet里面,doService,doDispatch,所有的请求和响应都会经过这里,可以在这里打一个断点观察我定义的视图解析器的有没有存在
//如果想要自定义一些定制化的功能,只需要写这个组件,将它交给springboot,springboot就会自动装配
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
public static class MyViewResolver implements ViewResolver {
//实现了ViewResolver的类就被当做视图解析器
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
建一个配置类,内部静态类(自定义视图解析器),并将它注入IOC。
之前知道Springmvc中所有的配置都会走dispatherServlet中,所以我进去DispatcherServlet类中查看,有方法是doService,doDispatch。
这两个方法是mvc中所有请求必须经过的地方,在doDispatch方法添加一个断点。调试一下。
可以发现我定义的视图解析器的确被加载了。
由此可推断springboot帮我们自动装配了。
消息转换器Formatter
可以在WebMvcAutoConfigretion中找到如下适配器
@Bean
@Override
public FormattingConversionService mvcConversionService() {
Format format = this.mvcProperties.getFormat();
WebConversionService conversionService = new WebConversionService(new DateTimeFormatters()
.dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
addFormatters(conversionService);
return conversionService;
}
显而易见的,这是一个转换器,而它获取了格式format,然后将日期转换格式完成转换。
比如,看一下DateTimeFormatters类
public class DateTimeFormatters {
...
public DateTimeFormatters dateFormat(String pattern) {
if (isIso(pattern)) {
this.dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE;
this.datePattern = "yyyy-MM-dd";
}
else {
this.dateFormatter = formatter(pattern);
this.datePattern = pattern;
}
return this;
}
...
}
它的默认实现就是年月日的格式
点进getFormat()可以发现,它是WebMvcProperties的方法,这说明我们也可以在配置文件中,进行配置。还有日期类也刚好在附近
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
@Deprecated
@DeprecatedConfigurationProperty(replacement = "spring.mvc.format.date")
public String getDateFormat() {
return this.format.getDate();
}
@Deprecated
public void setDateFormat(String dateFormat) {
this.format.setDate(dateFormat);
}
public Format getFormat() {
return this.format;
}
}
真是顺手牵羊。
如果配置了自己的格式化方式,就会注册到Bean中生效,我们可以在配置文件中配置日期格式化的规则
spring.mvc.format.date=dd/MM/yyyy
idea中会有提示,说明可以映射到。
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解,在官网中without是标粗的,标粗是很少见的,所以为什么不能加这个EnableWebMvc呢
我们可以加上看看会发生什么(作死的边缘疯狂试探)
也不能闭着眼去作死,看一下这个注释干了什么
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
它导入一个类,继续点
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired(required = false)
public void setConfigurers(List configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
}
这个注解:代理bean方法false?代理bean有哪些?这个方法说吧配置都加进去。
不懂,所以看源码WebMvcAutoConfiguration类
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
条件是没有它!
WebMvcConfigurationSupport这个类只是加载web的一些最基本配置,导入他会让我们的配置都失效(不是我说的,是狂老师说的)
原话是这样的:
@EnableWebMvc将WebMvcConfigurationSupport组件导入进来了;
而导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能!
在SpringBoot中会有非常多的扩展配置
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个@EnableWebMvc。
如果我们全面接管了SpringMVC了,我们之前SpringBoot给我们配置的静态资源映射一定会无效,测试一下。了解即可。
(看破不说破,后面是强行水完的,已经没办法全部接受了,属实能力有限)