SpringBoot对静态资源的映射规则
首先我们了解一下SpringBoot做什么事情
基于阿里云Spring Initializr创建的项目,在src/main/resource目录下自动创建static和template目录,我们猜static是放置静态资源的,template放置的是模板页面(需要配合模板引擎使用的)。
我们在static目录下分别新建了JS、CSS、图片来进行测试发现JS和CSS和图片都可以访问,SpringBoot本质就是简化了Spring + SpringMvc,它使用了自动配置,是基于XXAutoConfiguration.java和XXProperties.java这几个类的。所以我们要去寻找SpringBoot为SpringMvc提供的自动配置。
基于之前对AutoConfig的理解,来猜测SpringBoot可能会提供一个WebAutoConfig,利用查找类功能,来看一下那个最想
上面的方式是有点玄学,还有一种靠谱的方式就是查看官网的文档
自动配置ViewResolver 视图解析器 可以根据控制器方法的返回值得到视图View对象,再由视图对象决定如何渲染页面
ContentNegotiatingViewResolver 组合所有的视图解析器
BeanNameViewResolver
支持静态资源
webJars
静态资源文件夹 (初步怀疑 static就是)
自动注入了转换器(Converter)和格式化器(Formatter)
转换器 前端请求传递的数据封装到控制方法参数上,需要做类型匹配和类型转换
格式化器 日期字符串 转换为 具体的日期对象
HttpMessageConverters SpringMvc用于转换请求和响应的
控制器中返回JSON数据,就是由它转换的
它作为WebMvcAutoConfigurationAdapter构造方法参数,被直接注入到容器中
MessageCodesResolver 定制错误代码生成规则
支持静态首页和支持favicon小图标
ConfigurableWebBindingInitializer 舒适化Web数据绑定器
请求参数绑定到方法参数,以及前面的类型转换器和格式化器
源码验证
//WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
webJar方式管理静态资源
在上面源码中可以发现SpringBoot会判断前端发给后端的请求地址中是否有"/webjars/**"存在,如果有就去classpath:/META-INF/resources/webjars/下寻找。
什么是webJar,简单说就是把静态资源(客户端资源:JavaScript CSS等)打成Jar包,对资源进行统一依赖管理。一般情况下webJar的Jar是会放在Maven仓库中的。所以使用webJar和使用Java的Jar一样,到POM文件中添加webJar的坐标就可以了。
我们以使用JQuery为例
在WebJar官网找到JQuery
选择Build Tool 为Maven方式
选择相应的版本号
拷贝坐标
在项目的POM文件中粘贴坐标
在代码中具体使用资源
//-- 前端发过来的请求
http:localhost:8888/webjars/XX
//-- SpringBoot要做的事情
到指定路径:classpath:/META-INF/resources/webjars/寻找是否有XX资源存在
默认的静态资源路径
还是相同的位置,还是那个方法addResourceHandlers。在方法中有这样一段代码
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
可以理解为:如果请求地址中含有staticPathPattern的信息,就去getResourceLocations(this.resourceProperties.getStaticLocations())所代表的路径下找响应的资源或者处理者。
staticPathPattern
private String staticPathPattern = “/**”;
/**代表当前项目下的任意资源
可以这么理解:对于项目的任意请求,只要没有处理程序就去找getResourceLocations(this.resourceProperties.getStaticLocations()) getResourceLocations(参数)
把参数(参数是一个字符串数组)和{“/”}拼接在一起构成一个新的数组
参数: this.resourceProperties.getStaticLocations())
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
`private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { “classpath:/META-INF/resources/“,
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };`
结合上面两个变量的信息,我们得到两个结论
静态资源可以放在四个路径下或者使用webJar(本质还是META-INF/resources)
所有没有处理程序的请求都会到四个路径下寻找响应的资源
模板引擎
Thymeleaf
模板引擎
在SpringBoot中整合Thymeleaf
Maven仓库中获取Thymeleaf的坐标
spring-boot-starter-thymeleaf Thymeleaf的场景启动器
看ThymeleafAutoConfiguration 自动配置做了哪些事情
看ThymeleafProperties 在配置文件(application.yml)中可以配置哪些
测试页面
没有starter 自定义@Configuration -》 @Bean等方式来注入组件
找坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.1.18.RELEASE</version>
</dependency>
看自动配置类
在看具体代码之前首先会想Spring整合Thymeleaf时是如何整合,整合了3个Bean:视图解析器,模板解析器以及模板引擎。所以要看自动配置类是否帮我们把上面的三个Bean注入到IOC容器中
通过源码可以发现几个Bean已经都被自动配置了,那下面就是看具体的配置信息。
看ThymeleafProperties文件
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
}
通过这段代码我们至少可以获取三个信息
yaml配置文件中想要配置Thymeleaf 通过spring.thymeleaf.XX 来调用当前类中的setXXX方法
前缀是classpath:/templates/ 代表模板页面要写在template目录下
后缀是.html表示都是html文件
# 应用名称
spring.application.name=springboot-web
# 应用服务 WEB 访问端口
server.port=8080
# cache不是默认值
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=utf-8
spring.thymeleaf.prefix=classpath:/template/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML