【Java】【系列篇】【Spring源码解析】【三】【体系】【Resource体系】

news2024/10/6 14:28:25
主要用于加载配置资源等等

Resource

前提须知

ClassLoader类的getResource和getResourceAsStream方法是原生JDK中内置的资源加载文件的方式;Spring中资源模型顶级接口不是Resource,而是InputStreamSource接口;Spring为何自己实现一套资源加载方式?主要原因是JDK原生的URL资源加载方式,对于加载classpath或ServletContext中的资源没有标准的处理。

整体结构图(非全部)

image-20230116172022509

Spring中的资源模型

InputStreamSource

InputStreamSource接口只有一个getInputStream方法,实现了该接口的实现类都可以从中获取资源的输入流

image-20230116174909683

Resource

Resource是InputStreamSource的子接口,它是从底层资源的实际类型(例如文件或类路径资源)中抽象出来的资源描述符的接口,它代表的是可读的资源。

image-20230116175104929

EncodedResource

从类名可以看出它是编码后的资源,它的内部有个Resource类型的属性,说明它本身不是直接加载资源的

image-20230116175139984

ContextResource

ContextResource是从一个封闭的上下文中加载的资源(类似于ServletContext这种)的扩展接口,例如来自javax.servlet.ServletContext,也可以来自普通的类路径路径或相对的文件系统路径(在没有显式前缀的情况下指定,因此相对于本地ResourceLoader的上下文应用)

image-20230116175205689

WritableResource

支持写资源的接口,提供了输出流的访问器;它代表可写的资源

image-20230116175226245

Spring中资源加载方式

  • ClassLoader

ClassPathResource [classpath:/]
  如果是classpath开头的资源路径,Spring解析后会自动到类路径下找;

  • File

FileSystemResource [file:/]
  如果是file开头的资源路径,则会去文件系统中找;

  • URL

UrlResource [xxx:/]
  如果是 URL 支持的协议开头,则底层会使用对应的协议,去尝试获取相应的资源文件;

FileSystemResource

java.io.File的一个包装,区别在于它是订制于Spring的Resource体系下的.

image-20230116173943442

ClassPathResource

ClassPathResource表示从类路径获取的资源,通常使用线程上下文的ClassLoader进行资源加载.
我们的Web项目通常编译后,会将class文件存储在WEB-INF/classes下,Spring就可以通过ClassPathResource来访问这些文件.

image-20230116174333229

UrlResource

UrlResource 封装了 java.net.URL,可用于访问通常可通过 URL 访问的任何对象,如文件、HTTP 目标、FTP 目标等。所有 URL 都有一个标准化的字符串表示,这样就可以使用适当的标准化前缀来表示不同的URL类型。通常有:

  • file:用于访问文件系统路径
  • http:用于通过http协议访问资源
  • ftp:用于通过ftp访问资源

image-20230116174351275

其他Resource

ServletContextResource

这是ServletContext资源的Resource实现,它解析相关Web应用程序根目录中的相对路径。
它始终支持流(stream)访问和URL访问,但只有在扩展Web应用程序存档且资源实际位于文件系统上时才允许java.io.File访问。无论它是在文件系统上扩展还是直接从JAR或其他地方(如数据库)访问,实际上都依赖于Servlet容器。

image-20230116174832962

InputStreamResource

返回一个仅一次使用的流,如果你要多次使用流,不要选择它。InputStreamResource 是给定 InputStream 的资源实现。只有在没有特定的资源实现可用时,才应该使用它。特别是,尽可能选择 ByteArrayResource 或任何基于文件的资源实现。

image-20230116174815047

ByteArrayResource

这是一个给定字节数组的资源实现。它为给定的字节数组创建一个 ByteArrayInputStream。它对于从任何给定的字节数组加载内容都很有用,而不必求助于一次性使用的 InputStreamResource。

image-20230116174754441

ResourceLoader

整体结构图

image-20230116173025540

ResourceLoader

解析

从名称来看,我们可以了解到这是一个资源加载器,也正如我们所想的,该接口是用来加载资源(例如类路径或者文件系统中的资源)的策略接口。这个接口里面只有两个接口,一个获取指定路径的资源,一个是获取资源加载器的类加载器,如图:

image-20230117094738467

当然,我们也可以看到里面有一个常量,这是我们加载资源是的前缀(classpath:)

单文件加载--------------------------------------------------------

image-20230117142033563

DefaultResourceLoader

作用

DefaultResourceLoader是spring提供的一个默认的资源加载器,DefaultResourceLoader实现了ResourceLoader接口,提供了基本的资源加载能力。实现了单个资源文件的加载。
DefaultResourceLoader包含了一个protocolResolvers的set集,可以通过添加ProtocolResolver来提供不同协议资源的读取能力,默认情况下protocolResolvers是空的,我们可以通过添加ProtocolResolver扩展DefaultResourceLoader的能力。

解析

image-20230117101324007

如上图,这是DefaultResourceLoader实现了ResourceLoader的getResource方法,这个方法将非URL资源路径视为类路径资源(支持包含包路径的完整类路径资源名称),除非在子类重写getResourceByPath方法。我们再看getResourceByPath方法的实现:

image-20230117102258737

image-20230117102315748

我们可以看到,这个方法的内容是使用内部类ClassPathContextResource的,而内部类又使用了ClassPathResource,最终将路径转换成了类路径。当然,我们可以发现这个方法是protected类型的,它本身是可以被子类重写的,我们再看下图:

image-20230117102916576

我们可以发现,AbstractApplicationContext是继承了DefaultResourceLoader的,所以是有可能有子类ApplicationContext重写此方法的,实际上,如果引入了spring-web模块中的依赖,这时getResourceByPath会被几个Web级的子类重写该方法,如下图,红框中都是重写的:

image-20230117103542500

举个例子:

image-20230117103614795

补充:ProtocolResolver

ProtocolResolver是一个函数式接口,实现该接口可以通过自定义不同的协议来读取解析资源路径中的资源。

使用示例:

在resources目录下创建一个resource目录,并在resource目录下创建一个demo.txt文件,demo.txt文件内容可以随意,当程序运行时会从该路径下加载,并通过缓冲流读取

 public class DemoProtocolResolver implements ProtocolResolver {

    public static final String DEMO_PATH_PREFIX = "demo:";

    @Override
    public Resource resolve(String location, ResourceLoader resourceLoader) {
        if (!location.startsWith(DEMO_PATH_PREFIX)) {
            return null;
        }

        String realpath = location.substring(DEMO_PATH_PREFIX.length());
        String classpathLocation = "classpath:resource/" + realpath;
        return resourceLoader.getResource(classpathLocation);
    }

    public static void main(String[] args) throws Exception {
        // 实例化DefaultResourceLoader DemoProtocolResolver
        DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
        DemoProtocolResolver demoProtocolResolver = new DemoProtocolResolver();
        resourceLoader.addProtocolResolver(demoProtocolResolver);

        // ResourceLoader获取编写的demo.txt
        Resource resource = resourceLoader.getResource("demo:demo.txt");
        InputStream inputStream = resource.getInputStream();
        InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
        BufferedReader br = new BufferedReader(reader);
        String readLine;
        while ((readLine = br.readLine()) != null) {
            System.out.println(readLine);
        }
        br.close();
    }
}

ClassRelativeResourceLoader

解析

ClassRelativeResourceLoader扩展的功能是可以根据给定的class所在包或者所在包的子包下加载资源。

image-20230117135152161

FileSystemResourceLoader

JavaDoc

将普通路径解析为文件系统资源而不是类路径资源(后者是DefaultResourceLoader的默认策略)的ResourceLoader实现。

注意:普通路径将始终被解释为相对于当前虚拟机工作目录,即使它们以斜杠开头。(这与Servlet容器中的语义一致。)使用显式的“file:”前缀强制使用绝对文件路径。

解析

和ClassRelativeResourceLoader类似,重写了getResourceByPath方法:

image-20230117135618264

ServletContextResourceLoader

作用

可以从Servlet上下文的根目录加载资源。

解析

路径:/WEB-INF/test.xml

ServletContextResourceLoader是从上下文的根路径加载资源,上下文的根路径是webapp(在开发工具中比如eclipse中,指的就是webapp,当打成war包以后就是你项目打包的名字了...);

maven工程打包以后src/main/resources下的资源文件会被打到WEB-INF/classes下,所以需要在WEB-INF后添加classes

image-20230117140047502

多文件加载--------------------------------------------------------

image-20230117142011122

ResourcePatternResolver

解析

从下图我们就可以看出,ResourcePatternResolver支持Ant形式的带星号( * )的路径解析,从而支持多个资源文件的加载:

image-20230117105256924

PathMatchingResourcePatternResolver

我们在上面有说过Spring加载资源的三种方式,除了类路径、文件系统以及url这三种,我们还支持Ant风格路径模式的解析,PathMatchingResourcePatternResolver就是支持Ant风格路径模式解析的实现类。如图:

image-20230117141227094

image-20230117141347299

当然上面的是(classpath*:)这个多路径匹配模式,如果你使用的是(classpath:)的,那么你会使用DefaultResourceLoader或者你指定的资源加载器进行路径解析:

image-20230117141900322

ServletContextResourcePatternResolver

解析

ServletContextResourcePatternResolver是PathMatchingResourcePatternResolver的子类,相较于PathMatchingResourcePatternResolver,ServletContextResourcePatternResolver针对ServletContextResource做了针对性处理

image-20230117115742434

附录

Ant-style Patterns

Ant(路径匹配表达式)风格的通配符解析

PatternDescriptionExampleRemark
?匹配任何的单个字符example/?ork可以匹配:example/fork;example/work
*匹配0或者任意数量的字符file:C:/some/path/*.xml可以匹配C:/some/path下的所有xml文件
**匹配0个或者更多的目录classpath:com/mycompany/**/applicationContext.xml可以匹配mycompany和applicationContext.xml的任意目录,例如: classpath:com/mycompany/test/applicationContext.xml; classpath:com/mycompany/work/applicationContext.xml.

引用

https://www.cnblogs.com/coder-zyc/p/16464495.html

https://www.jianshu.com/p/646d801e055d

https://blog.csdn.net/seasonsbin/article/details/80914911

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

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

相关文章

Nessus 扫描web服务

系列文章 Nessus介绍与安装 Nessus Host Discovery Nessus 高级扫描 Nessus 扫描web服务 1.启动nessus cd nessus sh qd_nessus.sh2.进入nessus网站 https://192.168.3.47:8834/3.点击【New Scan】 4.点击【Web应用程序测试】 5.输入name【web扫描】,描述【web…

Lesson 2. 矩阵运算基础、矩阵求导与最小二乘法

文章目录一、NumPy 矩阵运算基础1. NumPy 中的矩阵表示2. NumPy 中特殊矩阵构造方法3. NumPy 中矩阵基本运算4. NumPy 中矩阵代数运算二、矩阵方程与向量求导方法1. 方程组求解与矩阵方程求解2. 向量求导运算2.1 向量求导基本方法2.2 常见向量求导公式三、最小二乘法的推导过程…

Vue3 函数式组件的开发方式

声明式组件和服务式组件 无论是使用第三方组件库,还是自己封装组件,有一类组件有些与众不同,那就是函数式/服务式组件,比如 Message 消息组件、Notification 通知组件、Loading 加载组件等等。 以 ElementPlus 组件库为例&#…

.net反序列化新手入门--Json.Net

**01 **Json.net简介 Json.net即Newtonsoft.Json,是.Net中开源的Json序列化和反序列化工具,官方地址:http://www.newtonsoft.com/json。 它虽然不是官方库,但凭借其优秀的性能获得了广大开发者的喜爱。 官网给出的性能比较&…

8大预测分析工具比较

什么是预测分析工具? 预测分析工具融合了人工智能和业务报告。这些工具包括用于从整个企业收集数据的复杂管道,添加统计分析和机器学习层以对未来进行预测,并将这些见解提炼成有用的摘要,以便业务用户可以对此采取行动。 预测的…

day17集合

1.Set集合 1.1Set集合概述和特点【应用】 不可以存储重复元素没有索引,不能使用普通for循环遍历 1.2Set集合的使用【应用】 存储字符串并遍历 public class MySet1 {public static void main(String[] args) {//创建集合对象Set<String> set new TreeSet<>()…

超级详细的几道python题(附答案)含解析、建议收藏

名字&#xff1a;阿玥的小东东 学习&#xff1a;python、正在学习c 主页&#xff1a;阿玥的小东东 目录 判断字符串 a “welcome to my world” 是否包含单词 b “world”&#xff0c;包含返回 True&#xff0c;不包含返回 False。 从 0 开始计数&#xff0c;输出指定字符串…

SSH使用入门

目录 .1 基础配置 1.1 vscode使用 1.2 HOST连接 .2 文件传输 .1 基础配置 1.1 vscode使用 拓展里搜索 然后点击remote里的设置 选择配置 然后填写配置 Hostname是你要ssh的服务器的ip地址 user是你要连接的服务器的用户名 Host可以随便写一个 如果有端口号也要对应修改 …

对于KMP的next数组的新发现,好像我们并不用回溯

目录 前言 发现 总结 博客主页&#xff1a;张栩睿的博客主页 欢迎关注&#xff1a;点赞收藏留言 系列专栏&#xff1a;c语言学习 家人们写博客真的很花时间的&#xff0c;你们的点赞和关注对我真的很重要&#xff0c;希望各位路过的朋友们能多多点赞并关注我&#xff0c;我会…

datax数据导入starrocks表报列数量不匹配错误,问题解决思路

背景在做客户数据导入任务的时候&#xff0c;需要将客户oracle的数据通过datax导入到 starrocks的表中&#xff0c;但是datax的配置文件中SQL查找客户数据的列数和要导入的starrocks表的列数都是相同且对应的&#xff0c;但是导入结果就是报了列数不对等的错误&#xff0c;Erro…

把代码贴进去自动找bug,这个debug神器自动修复仅需几秒

在编写程序时&#xff0c;无论是对于初学者还是对于专业开发人员&#xff0c;都会花费大量时间来调试或修复源代码错误&#xff0c;也就是 Debug。 这个过程繁琐复杂&#xff0c;包括 Bug 复现和 Bug 定位等环节。如果有了自动化的 Debug 程序&#xff0c;就可以显著提高编程实…

网络文件服务器:FileVista 8.9.3 Crack

FileVista 用于自托管文件共享的FileVista文件管理器 在几分钟内将您的网站变成一个网络文件服务器。 在您的网站上与您的客户或员工共享文件。 将您的机密文件存储在您自己的服务器上并对其进行完全控制。使您的用户只需使用 Web 浏览器即可从任何地方安全地访问、上传和组织文…

深度学习入门基础CNN系列——感受野和多输入通道、多输出通道以及批量操作基本概念

本篇文章主要讲解卷积神经网络中的感受野和通道的基本概念&#xff0c;适合于准备入门深度学习的小白&#xff0c;也可以在学完深度学习后将其作为温习。 如果对卷积计算没有概念的可以看本博主的上篇文章深度学习入门基础CNN系列——卷积计算 一、感受野&#xff08;receptive…

基于Java+SpringBoot+Vue+uniapp微信小程序零食商城系统设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【从零开始学习深度学习】47. Pytorch图片样式迁移实战:将一张图片样式迁移至另一张图片,创作自己喜欢风格的图片【含完整源码】

目录1. 图片样式迁移的方法介绍2. 读取内容图像和样式图像3. 图像的预处理和后处理4. 图像的抽取特征5.1 内容损失5.2 样式损失5.3 总变差损失5.4 损失函数6. 创建和初始化合成图像7. 训练模型并输出合成图像总结本文将介绍如何使用卷积神经网络自动将某图像中的样式应用在另一…

分享回顾|新岁序开,2023 和Jina AI共同码梦!

在坚持开放协作精神、具备全球影响力的 Jina AI 开源社区&#xff0c;每天都有来自世界各地的开发者来到这里&#xff0c;因为技术产生联结&#xff0c;因为联结产生共创。一直以来&#xff0c;我们都为拥有这样一个全球化、多元化和高速发展的社区而感到自豪和感激&#xff01…

golang解决跨域问题

文章目录前言一、跨域问题1.是什么2.跨域的特征&#xff08;跨域报错&#xff09;二、解决跨域问题的方法1.golang解决跨域问题2.简单请求3.非简单请求过程分析&#xff08;复杂请求&#xff09;:三、状态码设置为200依旧出错前言 今天中午在部署golang与vue搭建的一个项目时&…

JavaWeb开发(三)3.3——Spring Bean详解(基于XML方式)

一、Bean的概念 由 Spring IoC 容器负责创建、管理所有的Java对象&#xff0c;这些管理的对象称为 Bean&#xff0c;Bean 根据 Spring 配置文件中的信息创建。 二、基于XML方式管理bean对象 eg&#xff1a; <?xml version"1.0" encoding"UTF-8"?&…

JupyterLab,极其强大的 10 个秘密技巧

之前一篇文章&#xff1a;整理了上千个 Python 工具库&#xff0c;涵盖24个大方向 没想到火了。喜欢的可以看一下。 今天我给大家分享一下 Jupyter Lab 的一些内容。 JupyterLab 是 Jupyter 主打的最新数据科学生产工具&#xff0c;某种意义上&#xff0c;它的出现是为了取代…

瑞芯微的接口结构学习总结

MPI 接口使用的主要数据结构&#xff1a; 瑞芯微提供的媒体处理软件平台&#xff08;Media Process Platform&#xff0c;简称 MPP&#xff09;是适用于瑞芯微芯片系列的 通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理&#xff0c;其目的是为了屏蔽不 …