springboot web开发静态资源的映射规则

news/2024/5/16 19:00:00/文章来源:https://blog.csdn.net/wufagang/article/details/107573171

前言

我们之间介绍过SpringBoot自动配置的原理,基本上是如下:

xxxxAutoConfiguration:帮我们给容器中自动配置组件;
xxxxProperties:配置类来封装配置文件的内容;
web开发中都在org.springframework.boot.autoconfigure.web包下
今天看的静态资源映射规则都在org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration类中配置

态资源的映射规则

官方给了几个默认位置

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

什么意思

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

分析下源码

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration类中有
public void addResourceHandlers(ResourceHandlerRegistry registry) 这个方法是核心
但是这个方法是WebMvcAutoConfigurationg中的一个内部类(WebMvcAutoConfigurationAdapter )的方法:

封装配置属性的类:WebMvcProperties.class, ResourceProperties.class

 @Configuration(proxyBeanMethods = false)@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})@Order(0)public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {

addResourceHandlers方法分析:

public void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");} else {Duration cachePeriod = this.resourceProperties.getCache().getPeriod();//对webjars文件的映射,比如jquery,easyui等这些js,没错js也可以达成jar的方式CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();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)) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));}}}

针对webjars 部分分析

 //对webjars文件的映射,比如jquery,easyui等这些js,没错js也可以达成jar的方式CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();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));}

所有/webjars/**都从classpath:/META-INF/resources/webjars/路径下去找对应的静态资源。

什么是webjars?
就是以jar包的方式引入静态资源。

官网地址:http://www.webjars.org/。类似于maven仓库。

在这里插入图片描述

我们可以做个例子,将jquery引入到项目中

<dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.5.1</version>
</dependency>

项目依赖
在这里插入图片描述

会自动为我们引入jquery,要怎么使用呢?我们上面说过:
所有/webjars/*都从classpath:/META-INF/resources/webjars/路径下去找对应的静态资源。
所以我们启动项目,访问:http://localhost:8080/webjars/jquery/3.4.0/jquery.js即可。
这么说以后我们引用js框架都可以使用这种方式引用了

针对我们自己的静态资源进行的映射

//这部分是针对我们自己的静态资源进行的映射String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));}

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
在这里插入图片描述
“/**” 访问当前项目的任何资源,都去(静态资源的文件夹)找映射

ResourceProperties
public String[] getStaticLocations() {return this.staticLocations;}构造方法:private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};private String[] staticLocations;private boolean addMappings;private final ResourceProperties.Chain chain;private final ResourceProperties.Cache cache;public ResourceProperties() {this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;this.addMappings = true;this.chain = new ResourceProperties.Chain();this.cache = new ResourceProperties.Cache();}
WebMvcAutoConfiguration.getResourceLocations(new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"})
private static final String[] SERVLET_LOCATIONS = new String[]{"/"};
static String[] getResourceLocations(String[] staticLocations) {String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);return locations;}
所以上述代码经过我的翻译后成为了如下样子:registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/", "/")// 设置缓存时间.setCachePeriod(cachePeriod));

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

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

优先级从上到下。
所以,如果static里面有个index.html,public下面也有个index.html,则优先会加载static下面的index.html,因为优先级!
那我们就做个实验试试吧
分别放一个a.js
这里就自行实验吧

欢迎首页

欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;

@Beanpublic 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() {String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations());return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();}private Resource getIndexHtml(String location) {return this.resourceLoader.getResource(location + "index.html");}
classpath:/META-INF/resources/index.html
classpath:/resources/index.html
classpath:/static/index.html 
classpath:/public/index.html
/index.html

优先级从上到下。

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

favicon.ico

所有的 **/favicon.ico 都是在静态资源文件下找
2.2.x 前的版本
在此之前版本下默认是有一个默认的 favicon.ico 文件的,也就是咱们常说的绿叶子图标,相关的代码在 WebMvcAutoConfiguration 这个配置类中
2.2.x 版本以后
关于图标文件的处理,较新的版本做过一些改动,所以在 WebMvcAutoConfiguration 这个配置类中已经找不到关于 icon 相关的内容了,我们去 Github 看一下其改动

这里不赘述了…有需要的 可以去百度或者github上自行学习吧
在这里插入图片描述
这就是2.3.2官方描述
大致的意思就是:
和其他的静态资源一样,springboot在配置的静态资源中查找favicon.ico,如果存在这样的一个文件,它会自动用作应用程序的收藏夹

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_165770.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据治理-数据管理框架

DMBOK2提出的想法和概念在不同的组织中都可以应用&#xff0c;组织所采用的数据管理方法取决于某些关键要素&#xff0c;如其所处行业、所应用的数据范围、企业文化、成熟度、战略、愿景以及待解决的问题和挑战。 战略一致性模型和阿姆斯特丹模型&#xff0c;展示了组织管理数…

leetcode 1365. 有多少小于当前数字的数字

2023.9.2 本题直观的解法就是双层for循环暴力求解&#xff1a; 暴力解&#xff1a; class Solution { public:vector<int> smallerNumbersThanCurrent(vector<int>& nums) {vector<int> ans;for(int i0; i<nums.size(); i){int temp 0;//比当前元素…

【链表OJ 10】环形链表Ⅱ(求入环节点)

前言: &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 leetcode142. 环形链表 II 1.问题描述 2.代码思路 3.问题分析 leetcode142. 环形链…

mac帧 arp

1.分片 2.MSS max segment size 3.跨网络的本质 就是经历很多的子网或者局域网 4.将数据从A主机跨网络送到B主机的能力 IP和mac IP解决的是路径选择的问题 5.数据链路层 用于两个设备&#xff08;同一种数据链路节点&#xff09;之间进行传递 6.以太网ether 7.局域网通…

《爵士乐史》乔德.泰亚 笔记

第一章 【美国音乐的非洲化】 【乡村布鲁斯和经典布鲁斯】 布鲁斯&#xff1a;不止包括忧愁、哀痛 十二小节布鲁斯特征&#xff1a; 1.乐型&#xff08;A:主、B:属、C/D:下属&#xff09;&#xff1a;A→A→B→A→C→D→A→A 2.旋律&#xff1a;大三、小三、降七、降五 盲人…

C语言——指针基本语法

概述 内存地址 在计算机内存中&#xff0c;每个存储单元都有一个唯一的地址(内存编号)。 通俗理解&#xff0c;内存就是房间&#xff0c;地址就是门牌号 指针和指针变量 指针&#xff08;Pointer&#xff09;是一种特殊的变量类型&#xff0c;它用于存储内存地址。 指针的实…

MVC,MVP,MVVM的理解和区别

MVC MVC &#xff0c;早期的开发架构&#xff0c;在安卓里&#xff0c;用res代表V&#xff0c;activity代表Controller层&#xff0c;Model层完成数据请求&#xff0c;更新操作&#xff0c;activity完成view的绑定&#xff0c;以及业务逻辑的编写&#xff0c;更新view&#xf…

WordPress(5)在主题中添加文章字数和预计阅读时间

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 样式图一、添加位置二、找到主题文件样式图 提示:以下是本篇文章正文内容,下面案例可供参考 一、添加位置 二、找到主题文件 在主题目录下functions.php文件把下面的代码添加进去: // 文章字数…

javaScipt

javaScipt 一、JavaScript简介二、javaScript基础1、输入输出语法2、变量3、常量4、数据类型4.1、数字型 number4.2、字符串类型 string4.3、布尔类型 boolean4.4、未定义类型 undefined4.5、null 空类型4.6、typeof 检测变量数据类型 5、数据类型转换5.1、隐式转换5.2、显示转…

CESM2代码下载

这半年忙着毕业写论文&#xff0c;好久好久好久不更新了∠( ω)&#xff0f; &#xff0c;今天准备开个新坑 ๑乛◡乛๑&#xff0c;学习一下CESM&#xff08;Community Earth System Model&#xff09;&#xff0c;它是一个完全耦合的全球气候模型&#xff0c;可用于地球过去、…

MOS场效应管

导体三极管中参与导电的有两种极性的载流子&#xff0c;所以也称为双极型三极管。本文将介绍另一种三极管&#xff0c;这种三极管只有一种载流子参与导电&#xff0c;所以也称为单极型三极管&#xff0c;因为这种管子是利用电场效应控制电流的&#xff0c;所以也叫场效应三极管…

力扣:82. 删除排序链表中的重复元素 II(Python3)

题目&#xff1a; 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - …

Elasticsearch 分布式搜索——聚合

1.聚合的种类 聚合常见的有三类&#xff1a; **桶&#xff08;Bucket&#xff09;**聚合&#xff1a;用来对文档做分组 TermAggregation&#xff1a;按照文档字段值分组&#xff0c;例如按照品牌值分组、按照国家分组Date Histogram&#xff1a;按照日期阶梯分组&#xff0c;例…

LangChain学习笔记;给老师的ChatGPT使用指南;中国大模型顶级闭门会交流笔记;飞桨开源任务挑战大赛 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 飞桨PaddlePaddle开源任务挑战大赛&#xff0c;首届「开放原子开源大赛」等你参与 官网&#xff1a;https://competition.atomgit.com…

mac idea启动没反应 无法启动

遇到的问题如下&#xff1a; 启动idea&#xff0c;没反应 无法启动&#xff0c;不论破解还是别的原因&#xff0c;总之无法启动了 应用程序–找到idea–右击显示包内容–Contents–MacOS–打开idea 弹出框提示如下&#xff1a; 双击这个idea可执行文件 1&#xff09;先查看日志…

Springboot整合logback多节点日志文件加端口号区分

描述&#xff1a;正常情况下&#xff1a;在Springboot 项目的resources目录下创建一个logback-spring.xml的日志配置文件&#xff0c;简单配置如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?><configuration debug"false"&g…

1.4状态机模型

状态机简介&#xff1a; 1.大盗阿福 阿福是一名经验丰富的大盗。趁着月黑风高&#xff0c;阿福打算今晚洗劫一条街上的店铺。 这条街上一共有 N N N家店铺&#xff0c;每家店中都有一些现金。 阿福事先调查得知&#xff0c;只有当他同时洗劫了两家相邻的店铺时&#xff0…

【golang】调度系列之goroutine

前面的两篇&#xff0c;从相对比较简单的锁的内容入手(也是干货满满)&#xff0c;开始了go的系列。这篇开始&#xff0c;进入更核心的内容。我们知道&#xff0c;go应该是第一门在语言层面支持协程的编程语言(可能是我孤陋寡闻)&#xff0c;goroutine也完全算的上是go的门面。g…

Vue3实现可视化拖拽标签小程序

介绍 实现功能&#xff1a;可视化标签拖拽&#xff0c;双击标签可修改标签内容 HTML结构 <div class"box" v-move><div class"header">标签1</div><div dblclick"startEditing" v-if"!isEditing">{{content…

栈和队列篇

目录 一、栈 1.栈的概念及结构 1.1栈的概念 1.2栈的结构示意图 2.栈的实现 2.1支持动态增长的栈的结构 2.2压栈&#xff08;入栈&#xff09; 2.3出栈 2.4支持动态增长的栈的代码实现 二、队列 1.队列的概念及结构 1.1队列的概念 1.2队列的结构示意图 2.队列的实…