欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot —— 静态资源映射规则

程序员文章站 2022-07-10 17:38:13
...

SpringBoot —— 静态资源映射规则

SpringBoot默认为我们提供了静态资源的处理,其通过**自动配置类WebMvcAutoConfiguration**实现的。此类存放了与web开发相关的各种配置属性和方法。

1 官方文档的描述

官方文档

默认情况下,SpringBoot类路径中的

/static目录(或/public/resources/META-INF/resources)或ServletContext的根目录中提供静态内容。

它使用SpringMVC中的ResourceHttpRequestHandler

以便您可以通过添加自己的WebMvcConfigurer并重写addResourceHandlers方法来修改该行为。

名词解释:

前提,Maven 构建的SpringBoot 工程

  • 静态资源:css、js、img、font等

  • 类路径:项目下的/src/main/java/src/main/resources

SpringBoot —— 静态资源映射规则

2 静态资源映射规则

2.1 对哪些目录映射?

WebMvcAutoConfiguration类自动为我们注册了如下目录为静态资源目录,也就是说直接可访问到资源的目录。

优先级从上到下。

所以,如果static里面有个index.html,public下面也有个index.html,则优先会加载static下面的index.html,因为优先级!

classpath:/META-INF/resources/ 
classpath:/resources/
classpath:/static/ 
classpath:/public/
/:当前项目的根路径

2.2 目录映射 的理解

就我们在上面五个目录下放静态资源(比如:a.js等),可以直接访问(http://localhost:8080/a.js),类似于以前web项目的webapp下;放到其他目录下无法被访问。

2.3 为什么是这些目录?

2.3.1 看源码

自动配置类WebMvcAutoConfiguration

\org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.class

/**
 * 添加 资源处理器 的方法
 * 
 * addResourceHandlers 是 WebMvcAutoConfiguration 实现了接口  WebMvcConfigurer 的方法
 * 
 * @param registry  ResourceHandlerRegistry: 资源处理注册器
 *
 * resourceProperties: 资源 配置类 来封装配置文件的内容
 */
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    } else {
        Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
        CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
        // 以jar包的方式引入静态资源的映射
        // 所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源
        if (!registry.hasMappingForPattern("/webjars/**")) {
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }

        String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        if (!registry.hasMappingForPattern(staticPathPattern)) {
            // 当前项目的静态资源文件夹映射
            // staticPathPattern 是 /** 类路径
            // getStaticLocations() 是  "classpath:/META-INF/resources/", "classpath:/resources/", 					// "classpath:/static/", "classpath:/public/" 类路径下的子路径
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }

    }
}

资源配置类

\org\springframework\boot\autoconfigure\web\ResourceProperties.class

@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    // 默认的静态资源目录
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
    
    // 静态资源路径
    private String[] staticLocations;
    
    public ResourceProperties() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
    }
    
    // getter
    public String[] getStaticLocations() {
        return this.staticLocations;
    }

    // setter
    public void setStaticLocations(String[] staticLocations) {
        // 每个路径的末尾都追加 " / "
        this.staticLocations = this.appendSlashIfNecessary(staticLocations);
    }

    ......

2.3.2 分析的结论

(1)以jar包的方式引入静态资源webjar

所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源

localhost:8080/webjars/jquery/3.5.1/jquery.js

<!‐‐引入jquery‐webjar 在访问的时候只需要写webjars下面资源的名称即可‐‐>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>

SpringBoot —— 静态资源映射规则

(2)"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射

localhost:8080/abc === 去静态资源文件夹里面找abc

"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径

3 欢迎页(index.html)映射规则

3.1 官方描述(默认首页)

Spring Boot支持静态和模板欢迎页面。 它首先在配置的静态内容位置中查找index.html文件。

如果未找到,则寻找索引模板。 如果找到任何一个,它将自动用作应用程序的欢迎页面。

就是直接输入127.0.0.1:8080项目名称默认进入的页面

3.2 看源码

自动配置类WebMvcAutoConfiguration

\org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.class

/**
 * 往IOC容器中 添加 欢迎页 处理器映射器 组件
 */
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    // 设置 拦截器
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    // 设置 网络配置
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    // 
    return welcomePageHandlerMapping;
}

// 获取 欢迎页
private Optional<Resource> getWelcomePage() {zhaodaodi
    String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations());
    // 按照优先级,遍历默认静态资源目录后面拼接个index.html的数组
    // 比如:[/static/index.html, /public/index.html等等]
    // 找到第一个符合条件的 index.html 资源 返回                                            
    return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
}

// 给默认静态资源目录后面拼接个index.html并返回,比如:/static/index.html
private Resource getIndexHtml(String location) {
    return this.resourceLoader.getResource(location + "index.html");
}

// 是否可读
private boolean isReadable(Resource resource) {
    try {
        return resource.exists() && resource.getURL() != null;
    } catch (Exception var3) {
        return false;
    }
}

3.3 分析的结论

WebMvcAutoConfiguration类自动为我们注册了如下文件为默认首页

按照优先级找到第一个符合条件的index.html 页面。

优先级从上到下。

所以,如果static里面有个index.html,public下面也有个index.html,则static下面的index.html就是欢迎页

classpath:/META-INF/resources/index.html
classpath:/resources/index.html
classpath:/static/index.html 
classpath:/public/index.html
/index.html
/templates/index.html

4 网站图标(favicon.ico)

favicon.ico即Favorites Icon的缩写,它是一个图标,会出现在支持它的浏览器标题左边。
浏览器会打开网站会自动在网页项目的静态资源路径下

搜索这个指定文件名的图标文件,有就显示。

故我们的项目其实现在是不需要过多的配置的。

就是这样:

SpringBoot —— 静态资源映射规则

4.1 在2.2.X以上版本的改变

SpringBoot 的提交记录:

提交者wilkinsona,提交时间2019 Aug 21和Aug 23。
稍微读了一下他的操作,第一次把resources路径下的ico文件优先级提高到类路径之前,第二次就直接把默认带的spring网站图标文件favicon.ico文件给删了,即不提供默认的ico文件了,并且把原本在autoconfig里面的配置删了。

不提供默认的ico文件了,并且把原本在autoconfig里面的配置删了

4.2 用法

我们的页面在标签上添加下面一段代码并且资源文件放放对,即可成功让浏览器调到我们的图标文件,如果还没有不妨试试刷新浏览器缓存。

<link rel="icon" href="/img/my_favicon.ico" type="image/x-icon"/>
只要把my_favicon.ico.ico放到如下目录下,就会自动生效。
classpath:/META-INF/resources/ 
classpath:/resources/
classpath:/static/ 
classpath:/public/
/:当前项目的根路径