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

news2025/2/1 3:59:10

前言

我们之间介绍过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页面;被"/**"映射;

@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() {
            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.coloradmin.cn/o/964807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个月能做什么?成长感悟分享

一个月做了什么&#xff1f; 八月做了些什么&#xff1f; 单词打卡 第一件事情就是单词打卡 英语很差的我&#xff0c;一样继续打卡&#xff0c;今天是第736天 当你还在纠结扇贝和不背、可可英语哪一个好的时候&#xff0c;别人已经同时使用了 当你还在咨询学编程、敲代码需…

Linux上git的简单使用

git的作用&#xff1a;版本控制多人协作 客户端 磁盘上的文件-->本地仓库-->远端仓库 服务端 gitee和GitHub是基于git的商业化网站 git的命令行如何使用&#xff1f; 1、新建一个仓库 .git ignore 是忽略带有某些后缀的文件的上传。 例如&#xff1a;里面有 .sln …

输出图元(四)8-2 OpenGL画点函数、OpenGL画线函数

4.3 OpenGL画点函数 要描述一个点的几何要素&#xff0c;我们只需在世界坐标系中指定一个位置。然后该坐标位置和场景中已有的其他几何描述一起被传递给观察子程序。除非指定其他属性值&#xff0c;OpenGL 图元按默认的大小和颜色来显示。默认的图元颜色是白色&#x…

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

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

案例挑战—java反射

这里写目录标题 背景一、为什么要使用反射&#xff1f;二、反射的应用反射常用应用的思维导图2.1获取class对象的三种方法示例代码 2.2利用反射获取构造方法示例代码 2.3利用反射获取成员变量示例代码 2.4利用反射获取成员方法 三、总结四、升华 背景 由于在公司自研的新项目架…

Java 乘等赋值运算

下面这个题目是在一公司发过来的&#xff0c;如果你对 Java 的赋值运算比较了解的话&#xff0c;会很快知道答案的。 这个运算符在 Java 里面叫做乘等或者乘和赋值操作符&#xff0c;它把左操作数和右操作数相乘赋值给左操作数。 例如下面的&#xff1a;density * invertedRat…

LeetCode(力扣)236. 二叉树的最近公共祖先Python

LeetCode236. 二叉树的最近公共祖先 题目链接代码 题目链接 https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/ 代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val x # self.…

微服务--SkayWalking(链路追踪:国产开源框架)

SkayWalking&#xff1a;分布式系统的应用程序性能监视工具 作用&#xff1a;分布式追踪、性能指标分析、应用、服务依赖分析&#xff1b; SkayWalking性能剖析&#xff1a; 我操&#xff0c;能够定位到某一个方法会有多慢。。。 通过Tid查看全局所有的日志信息&#xff08…

企业架构LNMP学习笔记7

PHP介绍&#xff1a; HTML&#xff1a;超文本标记语言 http: 超文本传输协议 端口80 浏览器将html代码解析成web页面。 PHP&#xff1a;超文本预处理器。后端语言开发&#xff0c;页面上需要动态改变修改的&#xff0c;需要连接数据库查询数据&#xff0c;转为html。 主要…

学习笔记230810--vue项目中get请求的两种传参方式

问题描述 今天写了一个对象方式传参的get请求接口方法&#xff0c;发现没有载荷&#xff0c;ip地址也没有带查询字符串&#xff0c;数据也没有响应。 代码展示 错误分析 实际上这里的query是对象方式带参跳转的参数名&#xff0c;而get方法对象方式传参的参数名是parmas 解…

解决uView2 SwipeAction滑动单元格,点击按钮不关闭的问题

1、首先找到安装SwipeAction插件的位置&#xff0c;我的安装在一下位置 2.在 u-swipe-action-item.vue 文件内找到buttonClickHandler方法 3.在buttonClickHandler方法内添加代码 this.status close

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

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

MySQL中日期、时间直接相减的坑

前言 在牛客网上写一道 SQL 题时&#xff0c;需要计算两个日期之间相隔的秒数&#xff0c;我在写的时候直接将两个日期进行相减&#xff0c;得出来的值却不是相差的秒数。 情景再现 我在 MySQL 中进行了测试&#xff0c;得出的结论是&#xff1a;如果日期类型直接相减&#…

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

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

springboot web开发整合Freemarker 模板引擎

目录 Freemarker添加依赖配置文件ymlcontrollerhtml Freemarker 简介&#xff1a; FreeMarker 是一款 模板引擎&#xff1a; 即一种基于模板和要改变的数据&#xff0c; 并用来生成输出文本(HTML网页&#xff0c;电子邮件&#xff0c;配置文件&#xff0c;源代码等)的通用工具…

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉财经图书馆

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉财经图书馆

服务器上使用screen和linux的基本操作

配环境的一点小问题 我们尽量是去配置能满足代码的环境&#xff0c;而不要想着修改代码&#xff0c;让代码在我们的环境上跑起来。 服务器远程拷贝文件 scp -P 10001 c1316xxx.xxx.xx.xxx:/home/duj/local/cuda10.2.tar ./将c1316xxx.xxx.xx.xxx:/home/duj/local/cuda10.2.ta…

Elasticsearch 分布式搜索——聚合

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

MOS场效应管

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

HTML5+CSS3+JS小实例:科技感满满的鼠标移动推开粒子特效

实例:科技感满满的鼠标移动推开粒子特效 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport&qu…