Spring的资源Resource和ResourceLoader

news2025/7/19 5:44:34

两者区别和联系

ResourceResourceLoader 都是 Spring 框架中用于资源访问的接口

Resource 是“资源本身”,ResourceLoader 是“资源工厂/加载器”,负责创建 Resource。
​
Resource:Spring 统一抽象的“资源”对象,可以表示文件、类路径下的文件、URL、字节流等各种资源(统一封装各种类型的资源访问,屏蔽底层细节)
常见实现类:
ClassPathResource(类路径下的资源)
FileSystemResource(文件系统资源)
UrlResource(URL 资源)
ServletContextResource(Web 应用资源)
​
ResourceLoader: Spring 的资源加载器接口,负责根据资源路径加载并返回 Resource 对象(负责“解析”资源路径(如 classpath:、file:、http: 等),并返回对应的 Resource 实例。)
常用实现类:
DefaultResourceLoader(Spring 默认实现)
ApplicationContext(它本身就是 ResourceLoader 的实现)
​

Resource

Resouce家族族谱

img

ClassPathResource

ClassPathResource类:该资源类型在Spring中是非常常用的一种资源类型,用来访问类加载路径下的资源,相对于其他的Resource类型,该种类型在Web应用中可以自动搜索位于WEB-INF/classes下的资源文件,而无需使用绝对路径访问。

1、访问类路径下资源

@Test// 读取类路径下的资源 ClassPathResource(String path)
public void classPathResource() throws IOException {
  Resource classPathResource = new ClassPathResource("application.properties");
  InputStream inputStream = classPathResource.getInputStream();
  // 使用 apache下的 IOUtils 将流 转成 string
  String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
  System.out.println(content);
}

2、模块1项目内访问模块2项目下的资源

user-upload 模块下有两个项目

user-upload-api

user-upload-service

//user-upload-service 下访问 user-upload-api 下类路径资源
// ClassPathResource(String path, @Nullable ClassLoader classLoader)
    @Test
    void test() throws IOException {
        Resource resource2 = new ClassPathResource("application-api.properties", Constants.class.getClassLoader());
        System.out.println(IOUtils.toString(resource2.getInputStream(), StandardCharsets.UTF_8));
    }

FileSystemResource

FileSystemResource 是 Spring 框架中用于访问文件系统中资源的一个实现类

  • 你可以用它来访问任意路径下的文件(绝对路径或相对路径(相对于当前工作目录(working directory)的相对路径))。

@Test
    void fileSystemResource() throws IOException {
​
        // 查看当前工作目录
        System.out.println(System.getProperty("user.dir"));
        // 如果是相对路径 就是 工作目录+相对路径
        Resource resource = new FileSystemResource("src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8));
​
        // 2、绝对路径
        Resource resource2 = new FileSystemResource("/Users/liuyuanyuan/JavaProject/study/springboot/src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource2.getInputStream(), StandardCharsets.UTF_8));
    }

UrlResource

// 3. UrlResource - 访问URL资源
Resource urlResource = new UrlResource("https://example.com/file.txt");
URL url = urlResource.getURL();

ServletContextResource

ServletContextResource类:是ServletContext资源的Resource实现,用来访问相对于ServletContext路径下的资源。支持以流和URL的方式进行访问,但只有在扩展Web应用程序存档且资源实际位于文件系统上时才允许java.io.File访问。

  1. 实际应用场景:

@Service
public class WebResourceService {
    private final ServletContext servletContext;
    
    public WebResourceService(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
    
    public void processWebResource() {
        // 访问 WEB-INF 目录下的配置文件
        Resource configResource = new ServletContextResource(servletContext, "/WEB-INF/config.properties");
        
        // 访问静态资源
        Resource staticResource = new ServletContextResource(servletContext, "/static/images/logo.png");
        
        // 访问上传的文件
        Resource uploadResource = new ServletContextResource(servletContext, "/uploads/user-file.txt");
        
        try {
            if (configResource.exists()) {
                Properties props = new Properties();
                props.load(configResource.getInputStream());
                // 处理配置...
            }
            
            if (staticResource.exists()) {
                // 处理静态资源...
            }
            
            if (uploadResource.exists()) {
                // 处理上传的文件...
            }
        } catch (IOException e) {
            // 处理异常...
        }
    }
}
@Controller
public class FileController {
    private final ServletContext servletContext;
    
    public FileController(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
    
    @GetMapping("/download")
    public void downloadFile(HttpServletResponse response) throws IOException {
        // 获取要下载的文件资源
        Resource fileResource = new ServletContextResource(servletContext, "/uploads/document.pdf");
        
        if (fileResource.exists()) {
            // 设置响应头
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=document.pdf");
            
            // 将文件内容写入响应
            try (InputStream is = fileResource.getInputStream();
                 OutputStream os = response.getOutputStream()) {
                IOUtils.copy(is, os);
            }
        }
    }
    
    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
        // 获取上传目录的路径
        String uploadDir = servletContext.getRealPath("/uploads");
        
        // 创建上传目录
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        // 保存文件
        File destFile = new File(dir, file.getOriginalFilename());
        file.transferTo(destFile);
        
        return "redirect:/success";
    }
}

ResourceLoader

ResourceLoader 是资源加载器接口,用于加载资源。Spring 提供了默认实现 DefaultResourceLoader。

img

DefaultResourceLoader

ResourceLoader 提供多种资源方式的访问 提供getResource 方法

@Test
    void ResourceLoader() throws IOException {
​
        // 1、调用的是 ClassPathResource 加载类路径资源
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        Resource resource1 = resourceLoader.getResource("classpath:static/index.html");
        System.out.println(IOUtils.toString(resource1.getInputStream(), StandardCharsets.UTF_8));
​
        //2、调用的是 ClassPathContextResource 实际还是 ClassPathResource 他会帮我们去掉/ 加载类路径资源
        Resource resource2 = resourceLoader.getResource("/static/index.html");
        System.out.println(IOUtils.toString(resource2.getInputStream(), StandardCharsets.UTF_8));
​
        // 3、调用的是 UrlResource 加载URL资源 支持file访问本地资源(相对和绝对都支持) 支持访问网络资源
        Resource resource3_1 = resourceLoader.getResource("http://www.baidu.com");
        System.out.println(IOUtils.toString(resource3_1.getInputStream(), StandardCharsets.UTF_8));
        Resource resource3_2 = resourceLoader.getResource("file:src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource3_2.getInputStream(), StandardCharsets.UTF_8));
        Resource resource3_3 = resourceLoader.getResource("file:/Users/liuyuanyuan/JavaProject/study/springboot/src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource3_3.getInputStream(), StandardCharsets.UTF_8));
​
        // 4、调用的是 FileUrlResource 支持 绝对/相对 访问本地资源 其中相对是指项目的工作目录下
        Resource resource4_1 = resourceLoader.getResource("file:src/test/java/com/yuan/springboot/spring/resource/test.txt");
        Resource resource4_2 = resourceLoader.getResource("file:/Users/liuyuanyuan/JavaProject/study/springboot/src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource4_1.getInputStream(), StandardCharsets.UTF_8));
        System.out.println(IOUtils.toString(resource4_2.getInputStream(), StandardCharsets.UTF_8));
​
    }

FileSystemResource、FileUrlResource、UrlResource 总结

类名支持本地文件支持网络资源路径格式典型场景
FileSystemResource绝对/相对文件路径只操作本地文件
FileUrlResourcefile: 协议的 URL需要用 URL 方式访问本地文件
UrlResource任意 URL(http/file等)统一处理网络和本地资源

DefaultResourceLoader 是 ResourceLoader 的默认实现

核心方法是getResource

1、里面有个ProtocolResolver,允许用户自定义协议资源解决策略,作为 DefaultResourceLoader 的 SPI,它允许用户自定义资源加载协议,而不需要继承 ResourceLoader 的子类。 在这个接口类中只有一个方法。

所以有了 ProtocolResolver 后,我们不需要直接继承 DefaultResourceLoader,改为实现 ProtocolResolver 接口也可以实现自定义的 ResourceLoader

2、执行逻辑

若 location 以/开头,则调用 getResourceByPath()构造 ClassPathContextResource 类型资源并返回;
若 location 以 classpath:开头, 则构造 ClassPathResource 类型资源并返回,在构造该资源时,通过 getClassLoader()获取当前的 ClassLoader;
构造 URL,尝试通过它进行资源定位,若没有抛出 MalformedURLException 异常,然后判断是否为 FileURL,如果是则构造 FileUrlResource 类型资源,否则构造 UrlResource。若在加载过程中抛出 MalformedURLException 异常,则 委派 getResourceByPath() 实现资源定位加载。

FileSystemResourceLoader

  • FileSystemResourceLoader:适合你只想从本地文件系统加载资源,不需要支持 classpath 或网络资源的场景。

  • DefaultResourceLoader:适合需要支持多种资源类型(classpath、file、url等)的通用场景。

@Test
    void test() throws IOException {
        //实际上,FileSystemResourceLoader 的功能比 DefaultResourceLoader 更窄,它只能加载文件系统资源,不支持 classpath、http、ftp 等其他协议。
        // 而且你调用 getResource 还是在调用 FileSystemResourceLoader 父类DefaultResourceLoader的 getResource 方法 因为 FileSystemResourceLoader 根本没重写这个方法
        FileSystemResourceLoader fileSystemResourceLoader = new FileSystemResourceLoader();
​
        // 这个最终会调用 FileUrlResource
        Resource resource1 = fileSystemResourceLoader.getResource("src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource1.getInputStream(), StandardCharsets.UTF_8));
​
        // 这个会报错 因为他最后给你构造成 ClassPathContextResource 这个是从类路径下找资源的
        Resource resource2 = fileSystemResourceLoader.getResource("/Users/liuyuanyuan/JavaProject/study/springboot/src/test/java/com/yuan/springboot/spring/resource/test.txt");
        System.out.println(IOUtils.toString(resource2.getInputStream(), StandardCharsets.UTF_8));
​
    }

ResourcePatternResolver

ResourcePatternResolver接口继承了ResourceLoader, 是ResourceLoader的扩展

是 Spring 框架中用于批量加载资源的接口,支持通配符(如 *、**)和多种资源协议(classpath、file、http等)

PathMatchingResourcePatternResolver:Spring 默认实现,最常用

case

 @Test
    void resourcePatternResolver() throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
​
        // 查找 classpath static 下所有 txt 文件
        //classpath*: 表示所有 classpath 路径(包括依赖 jar 包里的资源)。
        //** 表示递归查找所有子目录。
        Resource[] resources = resolver.getResources("classpath*:static/**/*.txt");
        for (Resource resource : resources) {
            System.out.println(resource.getFilename());
        }
    }

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

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

相关文章

【AI实战】从“苦AI”到“爽AI”:Magentic-UI 把“人类-多智能体协作”玩明白了!

Hello,亲爱的小伙伴们!你是否曾经在深夜里,为了自动化点外卖、筛机票、抓网页数据焦头烂额?有没有幻想过哪天能出个“贴心AI管家”,一键点菜、搞定事务、自动操作网页,比你还懂你?更关键——还让…

Linux之 SPI 驱动框架- spi-mem 框架

一、框架变更的历程 1.1 旧框架图 1.2 新框架图 那么问题来了, 为什么要开发新的 SPI 存储器接口? 有了这个新的框架, SPI NOR 和SPI NAND 都可以基于相同的SPI控制器驱动进行支持了。m25p80 驱动将被修改成,使用spi-mem 接口&a…

振动分析 - 献个宝

1.一个自制的振动能量分析工具 这个分析工具似乎真的定位到了故障的具体位置。 1.1对一组实验室虚拟信号的分析结果: 1.2 对现场真实数据的分析结果 依照边频带的调制,和边频的缝隙宽度,基本定位到问题。 追加几份待看的文档: 齿轮结构的频谱特征 - 知乎使用 FFT 获得…

【论文阅读】——D^3-Human: Dynamic Disentangled Digital Human from Monocular Vi

文章目录 摘要1 引言2 相关工作3 方法3.1 HmSDF 表示3.2 区域聚合3.3. 变形场3.4. 遮挡感知可微分渲染3.5 训练3.5.1 训练策略3.5.2 重建损失3.5.3 正则化限制 4. 实验4.1 定量评估4.2 定性评价4.3 消融研究4.4 应用程序 5 结论 摘要 我们介绍 D 3 D^{3} D3人,一种…

高分辨率北半球多年冻土数据集(2000-2016)

关键数据集分类&#xff1a;冰冻圈数据集时间分辨率&#xff1a;10 year < x < 100 year空间分辨率&#xff1a;1km - 10km共享方式&#xff1a;开放获取数据大小&#xff1a;339.79 MB数据时间范围&#xff1a;2000-01-01 — 2016-12-31元数据更新时间&#xff1a;2022-…

基于开源AI智能名片链动2+1模式S2B2C商城小程序的管理与运营策略研究

摘要&#xff1a;本文通过分析开源AI智能名片链动21模式S2B2C商城小程序的技术架构与商业逻辑&#xff0c;探讨其在企业管理与运营中的实践价值。结合案例研究&#xff0c;论证该模式如何通过清晰的目标设定、动态反馈机制和资源整合能力&#xff0c;提升团队执行力与客户粘性。…

储能电站:风光储一体化能源中心数字孪生

在 “双碳” 目标引领下&#xff0c;我国能源产业加速向清洁低碳、绿色化转型&#xff0c;风能、太阳能等可再生能源的开发利用成为关键。然而&#xff0c;风能和太阳能的波动性、间歇性与随机性&#xff0c;给大规模接入电网带来挑战。储能技术的兴起&#xff0c;为解决这一难…

9. 现代循环神经网络

文章目录 9.1. 门控循环单元&#xff08;GRU&#xff09;9.1.1. 门控隐状态9.1.1.1. 重置门和更新门9.1.1.2. 候选隐状态9.1.1.3. 隐状态 9.1.2. 从零开始实现9.1.2.1. 初始化模型参数9.1.2.2. 定义模型 9.1.3. 简洁实现9.1.4. 小结 9.2. 长短期记忆网络&#xff08;LSTM&#…

视频太大?用魔影工厂压缩并转MP4,画质不打折!

在日常生活中&#xff0c;我们常常需要将视频文件转换成不同的格式以适应各种设备或平台的播放需求。魔影工厂作为一款功能强大且操作简单的视频转换工具&#xff0c;深受用户喜爱。本文中简鹿办公将手把手教你如何使用魔影工厂将视频转换为MP4格式&#xff0c;并进行个性化设置…

最宽温度范围文本格式PT1000分度表-200~850度及PT1000铂电阻温度传感器计算公式

常用PT铂电阻温度传感器 该图片来自网络&#xff0c;在此对图片作者表示感谢。 白色陶瓷面为测温面。 近距离图片。 常用的有PT100、PT500、PT1000&#xff0c;不常用的还有 PT50、PT200、PT10000等&#xff0c;PT代表铂电阻&#xff0c;后面的数字是零摄氏度时电阻值&#…

机器学习算法-sklearn源起

scikit-learn&#xff08;简称 sklearn&#xff09;是 Python 中最流行的开源机器学习库之一&#xff0c;基于 NumPy、SciPy 和 Matplotlib 构建。它提供了丰富的机器学习算法和工具&#xff0c;适用于数据挖掘和数据分析任务。以下是其核心特点的简介&#xff1a; 1、sklearn主…

注册并创建一个微信小程序

目录 &#xff08;一&#xff09;前往微信公众平台&#xff0c;并注册一个微信小程序账号 &#xff08;二&#xff09;配置微信小程序 &#xff08;三&#xff09;创建微信小程序项目 1.流程 1.1获取小程序ID 1.2下载微信开发者工具 1.3安装微信开发者工具 2.创建项目…

计算机网络——每一层的用到的设备及其作用

计算机网络基础 OSI参考模型TCP/IP协议族集线器&#xff08;Hub&#xff09;交换机&#xff08;Switch&#xff09;路由器&#xff08;Router&#xff09;功能特点无线路由器&#xff08;家庭宽带&#xff09;光猫功能 网关&#xff08;Gateway&#xff09;功能应用场景特点 IP…

【Web前端】JavaScript入门与基础(一)

JavaScript简介 JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”&#xff0c;指的是它不具备开发操作系统的能力&#xff0c;而是只用来编写控制其他大型应用程序的“脚本”。 JavaScript 是一种嵌入式&#xff08;embedded&#xff09;语言。它本身提供的核心语法不算…

前端大文件上传性能优化实战:分片上传分析与实战

前端文件分片是大文件上传场景中的重要优化手段&#xff0c;其必要性和优势主要体现在以下几个方面&#xff1a; 一、必要性分析 1. 突破浏览器/服务器限制 浏览器限制&#xff1a;部分浏览器对单次上传文件大小有限制&#xff08;如早期IE限制4GB&#xff09; 服务器限制&a…

Linux服务器配置深度学习环境(Pytorch+Anaconda极简版)

前言&#xff1a; 最近做横向需要使用实验室服务器跑模型&#xff0c;之前用师兄的账号登录服务器跑yolo&#xff0c;3张3090一轮14秒&#xff0c;我本地一张4080laptop要40秒&#xff0c;效率还是快很多&#xff0c;&#xff08;这么算一张4080桌面版居然算力能比肩3090&#…

超低延迟音视频直播技术的未来发展与创新

引言 音视频直播技术正在深刻改变着我们的生活和工作方式&#xff0c;尤其是在教育、医疗、安防、娱乐等行业。无论是全球性的体育赛事、远程医疗、在线教育&#xff0c;还是智慧安防、智能家居等应用场景&#xff0c;都离不开音视频技术的支持。为了应对越来越高的需求&#x…

Java 内存模型(JMM)深度解析:理解多线程内存可见性问题

Java 内存模型&#xff08;JMM&#xff09;深度解析&#xff1a;理解多线程内存可见性问题 在 Java 编程中&#xff0c;多线程的运用能够显著提升程序的执行效率&#xff0c;但与此同时&#xff0c;多线程环境下的一些问题也逐渐凸显。其中&#xff0c;内存可见性问题是一个关…

转移dp简单数学数论

1.转移dp问题 昨天的练习赛上有一个很好玩的起终点问题&#xff0c;第一时间给出bfs的写法。 但是写到后面发现不行&#xff0c;还得是的dp转移的写法才能完美的解决这道题目。 每个格子可以经过可以不经过&#xff0c;因此它的状态空间是2^&#xff08;n*m&#xff09;&…

动静态库--

目录 一 静态库 1. 创建静态库 2. 使用静态库 2.1 第一种 2.2 第二种 二 动态库 1. 创建动态库 2. 使用动态库 三 静态库 VS 动态库 四 动态库加载 1. 可执行文件加载 2. 动态库加载 一 静态库 Linux静态库&#xff1a;.a结尾 Windows静态库&#xff1a;.lib结尾…