SpringBoot 靜態(tài)資源原理
SpringBoot啟動默認(rèn)加載 xxxAutoConfiguration 類(自動配置類)
SpringMVC功能的自動配置類 WebMvcAutoConfiguration
所以我們就可以分析WebMvcAutoConfiguration 這個類
WebMvcAutoConfiguration.java
@Configuration( //此類不被代理
proxyBeanMethods = false
)
@ConditionalOnWebApplication( //是不是一個web的應(yīng)用, web應(yīng)用就包含SERVLET
type = Type.SERVLET
)
//是不是包含 Servlet DispatcherServlet WebMvcConfigurer web應(yīng)用本身就包含
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
//不包含 WebMvcConfigurationSupport 這個類
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
...
public WebMvcAutoConfiguration() {
}
內(nèi)部類 WebMvcAutoConfiguration ->WebMvcAutoConfigurationAdapter
@Configuration(
proxyBeanMethods = false
)
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
//關(guān)鍵
//EnableConfigurationProperties 開啟綁定和 將綁定的類添加到容器
//WebMvcProperties == "spring.mvc"
//ResourceProperties =="spring.resources"
//WebProperties =="spring.web"
//此處就說明了 我們 配置文件 為什么可以生效
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
//springboot 底層的代碼 如果類只有一個構(gòu)造器
//那么 所有的構(gòu)造器使用的類 都是在spring 的IOC容器里面獲取的
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
this.resourceProperties = (Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());
//此處就是將 一些我們?nèi)绻渲玫膶傩赃M(jìn)行賦值
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations;
this.mvcProperties.checkConfiguration();
}
}
@Bean
@ConditionalOnMissingBean //配置視圖解析器,此處不是重點,如果我們配置了,就不用springboot的
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
//靜態(tài)資源加載原理
//重點
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// resourceProperties.isAddMappings 是不是默認(rèn)禁用springboot 進(jìn)行靜態(tài)資源資源管理
/*
spring:
web:
resources:
add-mappings:true
默認(rèn)值是true, 就是不禁用
*/
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
// 如果我們使用了webjars 這里就是說明 為什么 webjars 的靜態(tài)資源可以訪問
// 會在每個webjars jar包里面尋找/META-INF/resources/webjars/ 路徑下的文件
//將他們 添加到spring boot 的靜態(tài)資源
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
/*
spring:
mvc:
static-path-pattern: /res/**
如果我們配置前綴, 所以資源路徑就會編程 "/res/**"
*/
// this.mvcProperties.getStaticPathPattern() = "/**" 默認(rèn)的靜態(tài)資源路徑規(guī)則
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
/*
spring:
web:
resources:
static-locations: classpath:/haha/
如果我們配置了 靜態(tài)資源路徑,就會在我們配置的靜態(tài)資源路徑下面尋找
this.resourceProperties.getStaticLocations() 就成了 /haha/
*/
// this.resourceProperties.getStaticLocations() = {"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
//默認(rèn)值,這里就說明了為什么springBoot的靜態(tài)資源需要放到這幾個文件夾下面
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
//如果使用原生的servlet,也將資源添加到原生的context下面
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
歡迎頁處理規(guī)則 WebMvcAutoConfiguration.java
//HandlerMapping:處理器映射器。保存了每一個Handler能處理哪些請求。
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext,
//將/index.html 傳入 //將前綴也傳入
this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping.java
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
//檢測 welcomePage /index.html 是不是存在
//檢測 前綴是否匹配
// 這里就說明了,如果我們使用了靜態(tài)資源使用的前綴,就無法匹配的默認(rèn)的歡迎頁
if (welcomePage != null && "/**".equals(staticPathPattern)) {
logger.info("Adding welcome page: " + welcomePage);
//設(shè)置默認(rèn)的歡迎頁
this.setRootViewName("forward:index.html");
} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { //這里是動態(tài)資源歡迎頁,使用模板
logger.info("Adding welcome page template: index");
this.setRootViewName("index");
}
}
網(wǎng)站圖標(biāo)配置
這里是瀏覽器的功能,瀏覽器會自動請求訪問/favicon.ico這個資源,如果存在瀏覽器就加上,和springboot 無關(guān)