1. 生效条件
// 我的自动配置类在这些自动配置之后配置
@AutoConfiguration(
after = {
DispatcherServletAutoConfiguration.class,
TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class
})
// 如果是web应用就生效,类型SERVLET、REACTIVE 响应式web
@ConditionalOnWebApplication(type = Type.SERVLET)
// 容器中没有这个Bean,才生效。默认就是没有
@ConditionalOnClass({
Servlet.class,
DispatcherServlet.class,
WebMvcConfigurer.class
})
// 容器中没有WebMvcConfigurationSupport类,才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
// 优先级
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
// 导入运行时的指标统计
@ImportRuntimeHints(WebResourcesRuntimeHints.class)
public class WebMvcAutoConfiguration {
}
2. 效果
-
放了两个Filter:
HiddenHttpMethodFilter
;页面表单提交Rest
请求(GET、POST、PUT、DELETE)FormContentFilter
:表单内容Filter
- GET(数据放URL后面)
- POST(数据放请求体)请求可以携带数据
- PUT、DELETE 的请求体数据会被忽略
-
给容器中放了
WebMvcConfigurer
组件;给SpringMVC添加各种定制功能- 所有的功能最终会和配置文件进行绑定
WebMvcProperties
:spring.mvc
配置文件WebProperties
:spring.web
配置文件
@Configuration(proxyBeanMethods = false) @Import(EnableWebMvcConfiguration.class) // 额外导入了其他配置 @EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware{ }
3. WebMvcConfigurer接口
提供了配置SpringMVC底层的所有组件入口
4. 静态资源规则源码
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
// 1. 规则一
addResourceHandler(
registry, this.mvcProperties.getWebjarsPathPattern(),
"classpath:/META-INF/resources/webjars/"
);
// 2. 规则二
addResourceHandler(
registry, this.mvcProperties.getStaticPathPattern(),
(registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(
this.servletContext, SERVLET_LOCATION
);
registration.addResourceLocations(resource);
}
});
}
- 规则一:访问:
/webjars/**
路径就去classpath:/META-INF/resources/webjars/
下找资源.- maven 导入依赖
<dependency> <groupId>org.webjars.npm</groupId> <artifactId>ant-design__icons-vue</artifactId> <version>7.0.1</version> </dependency>
- maven 导入依赖
- 规则二:访问:
/**
路径就去静态资源默认的四个位置找资源
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
- 规则三:静态资源默认都有缓存规则的设置
- 所有缓存的设置,直接通过配置文件:
spring.web
cachePeriod
:缓存周期;多久不用找服务器要新的。 默认没有,以s为单位cacheControl
HTTP缓存控制;https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching- useLastModified:是否使用最后一次修改。配合HTTP Cache规则
- 所有缓存的设置,直接通过配置文件:
如果浏览器访问了一个静态资源
index.js
,如果服务这个资源没有发生变化,下次访问的时候就可以直接让浏览器用自己缓存中的东西,而不用给服务器发请求。
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
5. EnableWebMvcConfiguration 源码
// SpringBoot 给容器中放 WebMvcConfigurationSupport 组件。
// 我们如果自己放了 WebMvcConfigurationSupport 组件,Boot的WebMvcAutoConfiguration都会失效。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration
extends DelegatingWebMvcConfiguration implements ResourceLoaderAware
{
}
HandlerMapping
:根据请求路径/a
找那个handler能处理请求WelcomePageHandlerMapping
:- 访问
/**
路径下的所有请求,都在以前四个静态资源路径下找,欢迎页也一样 - 找
index.html
:只要静态资源的位置有一个index.html
页面,项目启动默认访问
- 访问
6. 为什么容器中放一个WebMvcConfigurer
就能配置底层行为
WebMvcAutoConfiguration
是一个自动配置类,它里面有一个EnableWebMvcConfiguration
EnableWebMvcConfiguration
继承与DelegatingWebMvcConfiguration
,这两个都生效DelegatingWebMvcConfiguration
利用 DI 把容器中 所有WebMvcConfigurer
注入进来- 别人调用
DelegatingWebMvcConfiguration
的方法配置底层规则,而它调用所有WebMvcConfigurer
的配置底层方法。
7. WebMvcConfigurationSupport
提供了很多的默认设置。
判断系统中是否有相应的类:如果有,就加入相应的HttpMessageConverter
jackson2Present = ClassUtils.isPresent(
"com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
classLoader
);
jackson2XmlPresent = ClassUtils.isPresent(
"com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader
);
jackson2SmilePresent = ClassUtils.isPresent(
"com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader
);