当前位置: 首页 > article >正文

Spring的资源Resource和ResourceLoader

两者区别和联系

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 将流 转成 stringString 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)@Testvoid 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)的相对路径))。

@Testvoid 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 方法

@Testvoid 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等)的通用场景。

@Testvoid test() throws IOException {//实际上,FileSystemResourceLoader 的功能比 DefaultResourceLoader 更窄,它只能加载文件系统资源,不支持 classpath、http、ftp 等其他协议。// 而且你调用 getResource 还是在调用 FileSystemResourceLoader 父类DefaultResourceLoader的 getResource 方法 因为 FileSystemResourceLoader 根本没重写这个方法FileSystemResourceLoader fileSystemResourceLoader = new FileSystemResourceLoader();
​// 这个最终会调用 FileUrlResourceResource 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

 @Testvoid 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.lryc.cn/news/2385696.html

相关文章:

  • 字节跳动旗下火山引擎都覆盖哪些领域
  • 【AI实战】从“苦AI”到“爽AI”:Magentic-UI 把“人类-多智能体协作”玩明白了!
  • LeetCode面试经典150题梳理
  • ABP VNext + Orleans:Actor 模型下的分布式状态管理最佳实践
  • Linux之 SPI 驱动框架- spi-mem 框架
  • 振动分析 - 献个宝
  • 从脑电图和大脑记录中学习稳健的深度视觉表征
  • 【论文阅读】——D^3-Human: Dynamic Disentangled Digital Human from Monocular Vi
  • 高分辨率北半球多年冻土数据集(2000-2016)
  • Prompt Tuning:轻量级大模型微调全攻略
  • 【VBA 字典的引用和调用方法】
  • 基于开源AI智能名片链动2+1模式S2B2C商城小程序的管理与运营策略研究
  • 储能电站:风光储一体化能源中心数字孪生
  • iOS 直播特殊礼物特效实现方案(Swift实现,超详细!)
  • 9. 现代循环神经网络
  • 视频太大?用魔影工厂压缩并转MP4,画质不打折!
  • Python中tqdm进度条工具和enumerate函数的使用详解
  • 最宽温度范围文本格式PT1000分度表-200~850度及PT1000铂电阻温度传感器计算公式
  • 基于Netty架构的充电桩系统设计:服务器运维如何更好保障稳定性?
  • 操作系统学习笔记第1章 操作系统概述(灰灰题库
  • 后端开发实习生-抖音生活服务
  • 机器学习算法-sklearn源起
  • Keepalived 在不同场景下的高可用方案设计与最佳实践
  • 注册并创建一个微信小程序
  • CentOS 10:启动telnet服务
  • 计算机网络——每一层的用到的设备及其作用
  • OpenLayers 加载鹰眼控件
  • Eigen与OpenCV矩阵操作全面对比:最大值、最小值、平均值
  • 安全基础与协议分析
  • 【Web前端】JavaScript入门与基础(一)