7、Web开发:静态资源
在项目中需要使用到大量的 JS、CSS 等静态资源,如何导入静态资源呢?
7.1、存放位置
- 以前的 web 项目:放在 webapp 目录(或 web 目录)下;
-
Spring Boot 项目:静态资源映射
- 通过 webjars
- 通过 staticPathPattern
7.2、静态资源映射
在 Spring Boot 中,静态资源映射规则规定了静态资源的导入方式和存放路径等等;
静态资源映射规则在以下类中体现。
-
WebMvcAutoConfiguration类
- 配置类
- 定义了有关 Spring MVC 的 web 配置
-
WebMvcAutoConfigurationAdapter类
-
配置类:这个类是 Spring Boot 内部提供,专门用于处理用户自行添加的配置。
-
WebMvcAutoConfiguration 类的内部类
-
7.3、addResourceHandlers()
查看WebMvcAutoConfigurationAdapter类
的addResourceHandlers()方法
:
-
先做一个 if 判断:判断是否启动默认资源处理,未启动则结束方法体;
-
调用两个 addResourceHandler 重载方法:配置默认静态资源映射路径
(在 Spring Boot 的早期版本里,这两个重载方法没有被抽取出来,而是写在这个方法的内部,版本更新后将其抽取成方法)
7.4、默认静态资源映射
isAddMappings()
/**
* Whether to enable default resource handling.
*/
private boolean addMappings = true;
public boolean isAddMappings() {
return this.addMappings;
}
- 返回一个变量:addMappings;
-
变量含义:是否启动默认资源处理(即默认静态资源映射),默认为 true;
- 如果没有自定义静态资源映射路径:此时启动默认资源处理(变量值 true);
- 如果有自定义静态资源映射路径:此时禁用默认资源处理,而是采用自定义的配置(变量值 false)。
7.5、映射规则
- 如果采取默认资源处理,则遵守以下前两种规则:WebJars 和 staticPathPattern;
- 如果采取自定义,则遵守第三种规则:自定义映射路径。
7.5.1、webjars
-
通过 jar 包的方式引入静态资源,映射关系如下:
-
请求路径:
/webjars/**
-
资源路径:
classpath:/META-INF/resources/webjars/
-
请求路径:
-
映射规则:访问请求路径
/webjars/**
,会映射到相应的资源路径classpath:/META-INF/resources/webjars/
,寻找相应的资源 -
jar 包引入方式
- 以前的项目:先下载 jar 包,再将其导入项目;
- Spring Boot 项目:通过 Maven(pom 依赖)来引入 jar 包,相关依赖见 WebJars 网站;
举例:引入 jQuery 并访问
-
导入依赖
<dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.6.0</version> </dependency>
-
查看资源路径
-
通过请求路径访问资源
7.5.2、staticPathPattern
-
通过 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; }
-
-
映射规则:访问请求路径
/**
,会映射到相应的4个资源路径,寻找相应的资源。classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
举例:创建一个文件并访问
-
在 static 目录下创建一个文件:
target.txt
-
通过请求路径访问资源:成功访问
-
探讨资源访问优先级:
-
在类路径下的三个文件夹(resources、static、public)分别创建一个
target.txt
; -
两两测试,探究其优先级;
-
-
注:最外层的 resources 目录代表类路径,即
classpath:/
(注意与classpath:/resources/
区分) -
结论:类路径下的优先级:resources > static > public(即源码中的顺序优先级递减)
7.5.3、自定义映射路径
-
添加配置:
application.properties
spring.web.resources.static-locations=classpath:/jaywee/
-
注意:一旦自定义资源路径,会关闭默认资源处理(即默认静态资源映射),此时禁用所有默认静态资源映射(webjars 和 staticPathPattern 的四个映射路径)。
- 参考7.4,原因是 addMappings 的值为 false,结束了方法体;
- 因此没有后续的静态资源映射的相关设置,相当于禁用了默认静态资源映射;
7.6、小结
- Spring Boot 定义了静态资源映射规则,规定了静态资源的导入方式和存放路径;
- 上述规则,在
WebMvcAutoConfiguration类
的内部类WebMvcAutoConfigurationAdapter类
的addResourceHandlers()方法
中体现; - 如果自定义,则采取自定义映射规则;
- 如果没有自定义,则采取默认静态资源映射,包括以下两种映射规则:
-
webjars
-
请求路径:
/webjars/**
-
资源路径:
classpath:/META-INF/resources/webjars/
-
请求路径:
-
staticPathPattern:
-
请求路径:
/**
- 映射路径:4个,优先级依次递减
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
-
请求路径:
-
webjars
8、Web开发:首页和图标
启动 Spring Boot 项目并访问时
- 没有设置首页:会打开错误页面 Whitelabel Error Page;
- 没有设置图标:页面栏的左上角是浏览器的默认图标;
8.1、资源映射
类似7、静态资源
,设置首页和图标也有相应的规则。
在以下类中体现。
-
WebMvcAutoConfiguration类
- 配置类
- 定义了有关 Spring MVC 的 web 配置
-
EnableWebMvcConfiguration类
- 配置类
- WebMvcAutoConfiguration 类的内部类
8.2、welcomePageHandlerMapping()
查看EnableWebMvcConfiguration类
的welcomePageHandlerMapping()方法
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 = "/";
-
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;
}
测试
-
在 static 目录下创建
index.html
-
启动 Spring Boot 项目,成功访问首页
-
探讨首页映射优先级:
-
在类路径下的三个文件夹(resources、static、public)分别创建一个
index.html
; -
结论:优先级:resources > static > public(即源码中的顺序优先级递减)
-
8.3、图标
原理是类似的,结论:把图标正确命名:favicon.ico
并放在规定的资源映射路径中即可。
8.4、小结
首页和图标也可以当成静态资源,遵守静态资源映射规则。