你是否有这样的疑惑,为什么我的静态资源要放在xxxx...访问的时候为什么我可以以xxx...的方式访问。(xxx是让你自己思考的,看完文章你就知道了)接下来一一来解析。
首先,我们都知道自动配置类都是以autoConfigure结尾的,然后我们访问肯定是在web模块下的自动配置类,确认过眼神,发现WebMvcAutoConfiguration这个类是我们要找的类。(以上均为胡扯,你们直接看这个类就行)。我们目标锁定addResourceHandlers这个方法。接下来对他进行详解。我们来分析源码。
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
}
//首先在if中,看你是否在自己配置中禁用默认静态资源规则,isAddMappings默认为true
//使用spring.web.resources.add-mappings=false
//我们可以禁用默认路径规则
接着看
this.addResourceHandler(
registry,
"/webjars/**", "classpath:/META-INF/resources/webjars/");
这句话意思是访问/webjars/**的路径直接映射为/META-INF/resources/webjars/**。
接着看
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
我们可以看出this.mvcProperties.getStaticPathPattern()为你访问的路径,addResourceHandler的第三个参数为你的真实路径。我们点入this.mvcProperties.getStaticPathPattern()中的getStaticPathPattern方法发现为/**。
而下边的addResourceLocations方法只是一个容器添加操作,重点是this.resourceProperties.getStaticLocations()我们点进去就发现了熟悉的老朋友
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
根据版本差异,代码可能会有略微不同。
类比可以知道为什么访问‘/’可以看index.html
粗略的说一下
private Resource getWelcomePage() {
// var1为{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
String[] var1 = this.resourceProperties.getStaticLocations();
int var2 = var1.length;
//遍历目录去找index.html
for(int var3 = 0; var3 < var2; ++var3) {
String location = var1[var3];
Resource indexHtml = this.getIndexHtml(location);
if (indexHtml != null) {
return indexHtml;
}
}
ServletContext servletContext = this.getServletContext();
if (servletContext != null) {
return this.getIndexHtml((Resource)(new ServletContextResource(servletContext, "/")));
} else {
return null;
}
}