一、自动配置机制WebMvcAutoConfiguration
通过分析@EnableAutoConfiguration注解知道,Spring会用SpringFatoriesLoader载入一些配置,WebMvcAutoConfiguration是Boot-AutoConfigure自动载入的其中一个用于处理Web
1、 EnableAutoConfigurationAuto-configuration for EnableWebMvc WebMVC,会载入这个配置
2、@Configuration的嵌入机制,如果添加在一个类中的静态内部类中,这个static内部类会作为子配置被解析
3、WebMvcAutoConfiguration中的两个静态内部类WebMvcAutoConfigurationAdapter和EnableWebMvcConfiguration
@Configuration
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class })
public static classWebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter
4、@Configuration
EnableWebMvcConfigurationextends DelegatingWebMvcConfiguration
5、总结:相当于传统的MvcConfig用户配置,用@EnableWebMvc修饰一个@Configuration
EnableWebMvcConfiguration相当于@EnableWebMvc(DelegatingWebMvcConfiguration也是被@EnableWebMvc导入的),
WebMvcAutoConfigurationAdapter相当于用户自 定义配置(继承WebMvcConfigurerAdapter)
二、WebMvcAutoConfiguration中的详细内容
(一)静态资源处理
1、这个静态资源处理的框架是由WebMvcConfigurationSupport的一个Bean定义的,源码如下
/**
* Return a handler mapping ordered atInteger.MAX_VALUE-1 with mapped
* resource handlers. To configure resourcehandling, override
* {@link #addResourceHandlers}.
*/
@Bean
publicHandlerMapping resourceHandlerMapping() {
ResourceHandlerRegistryregistry = new ResourceHandlerRegistry(this.applicationContext,
this.servletContext,mvcContentNegotiationManager());
addResourceHandlers(registry);
AbstractHandlerMappinghandlerMapping = registry.getHandlerMapping();
if(handlerMapping != null) {
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
handlerMapping.setInterceptors(newResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
handlerMapping.setCorsConfigurations(getCorsConfigurations());
}
else{
handlerMapping= new EmptyHandlerMapping();
}
returnhandlerMapping;
}
2、@EnableWebMvc和EnableWebMvcConfiguration继承模板框架类
子类(WebMvcAutoConfigurationAdapter)通过适配器模式重载addResourceHandlers(registry),完成扩展
3、适配器WebMvcAutoConfigurationAdapter载入外部配置(SpringBoot默认配置)
使用@EnableConfigurationProperties和@ConfigurationPropertis机制,为两个Component
ResourceProperties和WebMvcProperties装配属性(原理请参考笔记二)
4、ResourceProperties内容
String[]SERVLET_RESOURCE_LOCATIONS = { "/" };
String[]CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/","classpath:/resources/",
"classpath:/static/","classpath:/public/" };
String[]RESOURCE_LOCATIONS;
static{
RESOURCE_LOCATIONS= new String[CLASSPATH_RESOURCE_LOCATIONS.length
+SERVLET_RESOURCE_LOCATIONS.length];
System.arraycopy(SERVLET_RESOURCE_LOCATIONS,0, RESOURCE_LOCATIONS, 0,
SERVLET_RESOURCE_LOCATIONS.length);
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS,0, RESOURCE_LOCATIONS,
SERVLET_RESOURCE_LOCATIONS.length,CLASSPATH_RESOURCE_LOCATIONS.length);
}
//Enable default resource handling.
booleanaddMappings = true;
5、使用默认属性注册ResourceHandlers
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod));
}
//映射规则:/**
String staticPathPattern =this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(
//映射位置
this.resourceProperties.getStaticLocations())
.setCachePeriod(cachePeriod));
//最后相当于<mvc:resources mapping="/**" location="classpath:/resources"/>
//<mvc:resources mapping="/**" location="classpath:/static/"/>
//<mvc:resources mapping="/**" location="classpath:/public/"/>
}
}