SpringBoot⑦静态资源和欢迎页面

8、静态资源和欢迎页面

在项目中需要使用到大量的 JS、CSS 等静态资源,如何导入静态资源呢?

  • 以前的 web 项目:放在 webapp 目录(或 web 目录)下;
  • Spring Boot 项目静态资源映射
    1. 通过 webjars
    2. 通过 staticPathPattern

8.1、静态资源映射

Spring Boot 中,静态资源映射规则规定了静态资源的导入方式和存放路径等等;

静态资源映射规则在以下类中体现。

  1. WebMvcAutoConfiguration类

    • 配置类
    • 定义了有关 Spring MVCweb 配置

    image-20211005232118935

  2. WebMvcAutoConfigurationAdapter类

    • 配置类:这个类是 Spring Boot 内部提供,专门用于处理用户自行添加的配置

    • WebMvcAutoConfiguration 类的内部类

      image-20211005232311892

8.1.1、addResourceHandlers()

查看WebMvcAutoConfigurationAdapter类addResourceHandlers()方法

  • 先做一个 if 判断:判断是否启动默认资源处理,未启动则结束方法体;

  • 调用两个 addResourceHandler 重载方法:配置默认静态资源映射路径

    (在 Spring Boot 的早期版本里,这两个重载方法没有被抽取出来,而是写在这个方法的内部,版本更新后将其抽取成方法)

image-20211006193507550

8.1.2、默认静态资源映射

isAddMappings()

/**
* Whether to enable default resource handling.
*/
private boolean addMappings = true;

public boolean isAddMappings() {
   return this.addMappings;
}
  1. 返回一个变量:addMappings
  2. 变量含义:是否启动默认资源处理(即默认静态资源映射),默认为 true
    • 如果没有自定义静态资源映射路径:此时启动默认资源处理(变量值 true);
    • 如果自定义静态资源映射路径:此时禁用默认资源处理,而是采用自定义的配置(变量值 false)。

8.2、映射规则

  • 如果采取默认资源处理,则遵守以下前两种规则:WebJarsstaticPathPattern
  • 如果采取自定义,则遵守第三种规则:自定义映射路径。

8.2.1、webjars

  1. 通过 jar 包的方式引入静态资源,映射关系如下
    • 请求路径/webjars/**
    • 资源路径classpath:/META-INF/resources/webjars/
  2. 映射规则:访问请求路径/webjars/**,会映射到相应的资源路径classpath:/META-INF/resources/webjars/,寻找相应的资源
  3. jar 包引入方式
    • 以前的项目:先下载 jar 包,再将其导入项目;
    • Spring Boot 项目:通过 Mavenpom 依赖)来引入 jar 包,相关依赖见 WebJars 网站

举例:引入 jQuery 并访问

  1. 导入依赖

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>3.6.0</version>
    </dependency>
    
  2. 查看资源路径

    image-20211006181058586

  3. 通过请求路径访问资源

    image-20211006183801089

8.2.2、staticPathPattern

  1. 通过 staticPathPattern 变量映射静态资源,映射关系如下:

    • 请求路径this.mvcProperties.getStaticPathPattern()

      • 返回一个变量:staticPathPattern
      • 变量含义:静态资源的路径模式。默认为/**,表示当前项目的任意资源。
      /**
       * Path pattern used for static resources.
       */
      private String staticPathPattern = "/**";
      
      public String getStaticPathPattern() {
          return this.staticPathPattern;
      }
      
    • 资源路径this.resourceProperties.getStaticLocations()

      • 返回一个变量:staticLocations
      • 变量含义:静态资源的位置,默认值为数组CLASSPATH_RESOURCE_LOCATIONS
        • classpath:/META-INF/resources/
        • classpath:/resources/
        • classpath:/static/
        • classpath:/public/
      private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
      		"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
      
      private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
      
      public String[] getStaticLocations() {
         return this.staticLocations;
      }
      
  2. 映射规则:访问请求路径/**,会映射到相应的4个资源路径,寻找相应的资源。

    • classpath:/META-INF/resources/
    • classpath:/resources/
    • classpath:/static/
    • classpath:/public/

举例:创建一个文件并访问

  1. static 目录下创建一个文件:target.txt

  2. 通过请求路径访问资源:成功访问

    image-20211007020615610

  3. 探讨资源访问优先级

    • 在类路径下的三个文件夹(resourcesstaticpublic)分别创建一个target.txt

    • 两两测试,探究其优先级;

  • :最外层的 resources 目录代表类路径,即classpath:/(注意与classpath:/resources/区分)

  • 结论类路径下的优先级:resources > static > public(即源码中的顺序优先级递减)

    image-20211007024346211

8.2.3、自定义映射路径

  • 添加配置:application.properties

    spring.web.resources.static-locations=classpath:/jaywee/
    
  • 注意一旦自定义资源路径,会关闭默认资源处理(即默认静态资源映射),此时禁用所有默认静态资源映射(webjarsstaticPathPattern 的四个映射路径)。

    • 参考7.4,原因是 addMappings 的值为 false,结束了方法体;
    • 因此后面的代码不会运行,相当于禁用了默认静态资源映射;

8.3、欢迎页面(首页)

启动并访问 Spring Boot 项目时:

  • 没有设置首页:会打开错误页面 Whitelabel Error Page
  • 没有设置图标:页面栏的左上角是浏览器的默认图标;

image-20211007160204997

首页index.html,也可以当做是静态资源,也遵守静态资源映射规则。

8.3.1、welcomePageHandlerMapping()

查看EnableWebMvcConfiguration类welcomePageHandlerMapping()方法

image-20211007161321101

8.3.2、getWelcomePage()

获取欢迎页

private Resource getWelcomePage() {
   for (String location : this.resourceProperties.getStaticLocations()) {
      Resource indexHtml = getIndexHtml(location);
      if (indexHtml != null) {
         return indexHtml;
      }
   }
   ServletContext servletContext = getServletContext();
   if (servletContext != null) {
      return getIndexHtml(new ServletContextResource(servletContext, SERVLET_LOCATION));
   }
   return null;
}

使用 foreach 循环,把getStaticLocations()中的每个值依次赋给变量 location

  • location-- getStaticLocations() :四个资源路径,具体见7.5.2

  • 调用 getIndexHtml() 方法,判断非空则返回

  • 如果 staticLocations 的四个资源路径下都没有index.html,获取 servletContext 上下文对象

    • 如果上下文对象非空,则调用并返回 getIndexHtml

    • 参数:上下文对象SERVLET_LOCATION

      private static final String SERVLET_LOCATION = "/";
      

8.3.3、getIndexHtml()

根据路径获取首页

  • 重载方法,参数为获取 location 路径下对应的资源;
  • 如果 location 路径下的资源存在index.html,则返回该页面,否则返回 null
private Resource getIndexHtml(String location) {
    return getIndexHtml(this.resourceLoader.getResource(location));
}

private Resource getIndexHtml(Resource location) {
    try {
        Resource resource = location.createRelative("index.html");
        if (resource.exists() && (resource.getURL() != null)) {
            return resource;
        }
    }
    catch (Exception ex) {
    }
    return null;
}

8.3.4、测试

  1. static 目录下创建index.html

    image-20211007165107882

  2. 启动 Spring Boot 项目,成功访问首页

    image-20211007165217738

  3. 探讨首页映射优先级

    • 在类路径下的三个文件夹(resourcesstaticpublic)分别创建一个index.html

    • 结论优先级:resources > static > public(即源码中的顺序优先级递减)

8.4、小结

  1. Spring Boot 定义了静态资源映射规则,规定了静态资源的导入方式和存放路径;
  2. 上述规则,在WebMvcAutoConfiguration类的内部类WebMvcAutoConfigurationAdapter类addResourceHandlers()方法中体现;
  3. 如果自定义,则采取自定义映射规则;
  4. 如果没有自定义,则采取默认静态资源映射,包括以下两种映射规则:
    • webjars
      • 请求路径/webjars/**
      • 资源路径classpath:/META-INF/resources/webjars/
    • staticPathPattern
      • 请求路径/**
      • 映射路径:4个,优先级依次递减
        1. classpath:/META-INF/resources/
        2. classpath:/resources/
        3. classpath:/static/
        4. classpath:/public/
  5. 首页也可以当成静态资源,遵守静态资源映射规则。
posted @ 2021-10-10 11:58  Jaywee  阅读(313)  评论(0编辑  收藏  举报

👇