SpringBoot中静态资源的访问,在SpringBoot的官方文档中这样写着
默认的,Spring Boot服务静态资源访问目录是叫 /static ( 或者 /public或者 /resources 或者 /meta-INF/resources) 文件夹或者 ServletContext。它使用来自 Spring MVC 的ResourceHttpRequestHandler,因此你可以通过添加你自己的WebMvcConfigurer修改并重写addResourceHandlers方法去修改静态资源目录。
在独立的 Web 应用程序中,容器中的默认 servlet 也被启用并充当回退,ServletContext如果 Spring 决定不处理它,则从根提供内容。大多数情况下,这不会发生(除非您修改默认的 MVC 配置),因为 Spring 始终可以通过DispatcherServlet.
默认情况下,资源映射在 上/**,但您可以使用spring.mvc.static-path-pattern属性对其进行调整。例如,将所有资源重新分配到/resources/**可以实现如下:
SpringBoot为什么这么方便呢?因为他内置了许多starter(启动器)并且SpringBoot可以实现自动装配。那默认的配置好的静态资源目录是从哪来的呢?我们一一剖析。
SpringBoot启动默认加载,xxxAutoConfiguration 类(自动装配类),SpringMVC的自动装配类叫WebMvcAutoConfiguration
我们可以看到这是一个配置类,当WebApplication是Servlet时加载,他初始化了一些参数我们可以知道这些就是我们返回视图时自动添加的前缀什么的。
既然是配置类我们就看看他到底配了什么
其中WebMvcAutoConfigurationAdapter又是一个配置类,加载他时绑定了WebMvcProperties.class和WebProperties.class
那配置文件的相关属性到底和谁进行了绑定?
我们点进WebMvcProperties 和 WebProperties发现 @ConfigurationProperties(prefix = "spring.mvc") 和 @ConfigurationProperties("spring.web")说明这两个类是和配置文件进行绑定的。WebMvcAutoConfigurationAdapter只有一个有参构造器,那么这个有参构造器的参数都会直接从容器中获取。
WebProperties webProperties:是获取我们配置文件中的和spring.web相关的配置的。
WebMvcProperties webMvcProperties:是获取我们配置文件中的和spring.mvc相关的配置的。
...
继续往下看我们可以看到addResourceHandlers 添加资源处理器方法。
这个方法的第一行是判断初始化后,resourceProperties这个属性是不是添加了映射。我们不难发现,后面是配置静态资源的,如果我们在配置文件中给这个属性设置了false那么他会return;不会执行后面的静态资源的配置。我们点进去发现里面直接返回了addMappings这个属性,属性的默认值是true。这表示SpringBoot在默认是启用静态资源映射的。
下面有这些语句。
addResourceHandler(registry, "/webjars/**", "classpath:/meta-INF/resources/webjars/");
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);
}
});
addResourceHandler(registry, "/webjars/**", "classpath:/meta-INF/resources/webjars/");这个是配置静态资源的例如css什么的。我们可以不用管。
然后它配置了registry,this.mvcProperties.getStaticPathPattern(), registration这三个参数,其中registration这个参数把resourceProperties.getStaticLocations()添加到ResourceLocations中,我们点进去可以看到
CLASSPATH_RESOURCE_LOCATIONS这个数组默认值是
{ "classpath:/meta-INF/resources/","classpath:/resources/", "classpath:/static/", "classpath:/public/" }
这里我们发现这里默认定义的参数很SpringBoot文档中定义的那四个默认静态资源访问路径一致。
我们接着看,它先判空当前的servletContext属性,不为空就把 servletContext 和 SERVLET_LOCATION 作为参数创建一个ServletContextResource对象。
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
SERVLET_LOCATION 是什么?我们点一下看到
这个就是我们的路径模式,默认是 ""
我们点进ServletContextResource对象看看,我们可以看到,它内置了当前的web容器和一个path
public ServletContextResource(ServletContext servletContext, String path) {
// check ServletContext
Assert.notNull(servletContext, "Cannot resolve ServletContextResource without ServletContext");
this.servletContext = servletContext;
// check path
Assert.notNull(path, "Path is required");
String pathToUse = StringUtils.cleanPath(path);
if (!pathToUse.startsWith("/")) {
pathToUse = "/" + pathToUse;
}
this.path = pathToUse;
}
看到这里我们就明白,我们的静态资源访问目录在底层是这样实现的,我们可以通过配置文件进行更改。这个路径模式也可以进行更改。今天的源码解析就写到这里谢谢大家的观看,讲得不好多多包涵!



