Spring 资源

最后更新: 2024-01-30 20:15:57 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

org.springframework.core.io.Resource 为 Spring API 提供统一句柄,所表示的内容可以位于文件、 类路径条目、URL、servlet 上下文、字节数组或已打开的流中。 该抽象描述访问能力;它不会让每个资源都可寻址、可重复读取、可写或由文件支持。

Resource 契约 #

Resource 扩展了 InputStreamSource。getInputStream() 是基本操作,而 exists()、isReadable()、isOpen()、isFile()、contentLength()、 lastModified() 和 getDescription() 等方法暴露能力或元数据。

重要实现包括:

  • ClassPathResource:用于类加载器或类相对条目;
  • FileSystemResource 和 PathResource:用于文件系统内容;
  • UrlResource:用于 JVM 支持的 URL;
  • ServletContextResource:用于 Web 应用路径;
  • ByteArrayResource:用于可重复读取的内存字节;以及
  • InputStreamResource:用于已打开的、通常只能使用一次的流。

调用方拥有 getInputStream() 返回的每个流,并必须关闭它。 isOpen() 尤其重要:InputStreamResource 包装已打开的句柄,不能安全地重复读取; 文件和字节数组资源则可以在每次调用时打开新流。

加载和相对解析 #

ResourceLoader.getResource(String) 将位置转换为一个资源。 每个 ApplicationContext 都是资源加载器。前缀选择明确语义:

  • classpath:com/example/report.html 选择类路径资源。
  • file:/srv/app/report.html 选择文件系统 URL。
  • https://example.net/schema.json 选择 URL 资源。

无前缀位置相对于上下文。ClassPathXmlApplicationContext 将其解释为类路径位置, FileSystemXmlApplicationContext 将其解释为文件系统位置,Web 应用上下文则将其解释为 servlet 上下文位置。 库代码应请求 Resource 或 ResourceLoader,而不是假设一种默认位置。

ResourcePatternResolver 将加载扩展到位置模式和多个匹配项。 classpath*: 搜索所有匹配的类路径根;Ant 风格通配符通过模式解析生效, 而不是通过单资源 ResourceLoader 契约生效。

注入资源 #

Spring 可以使用外围应用上下文作为加载器,将位置字符串转换为 Resource:

java
@Component
final class ReportRenderer {
    private final Resource template;

    ReportRenderer(@Value("${report.template:classpath:reports/daily.html}")
                   Resource template) {
        this.template = template;
    }
}

构造器注入使依赖可见,并允许测试提供 ByteArrayResource。 当位置随操作变化时注入 ResourceLoader;只有应用确实有意接受多个匹配项时, 才注入 Resource[] 或 ResourcePatternResolver。

存在性、可重复读取和写入 #

exists() 是探测而不是预留;内容可能在打开前消失。 当正确性依赖访问成功时,优先打开资源并处理产生的 IOException。 元数据操作也可能需要 I/O,而远程 URL 可能缓慢或不可用。

WritableResource 增加 isWritable() 和 getOutputStream()。 FileSystemResource 和 PathResource 实现该接口,而打包 JAR 内的类路径资源不实现。 写入代码应要求 WritableResource,而不是根据位置字符串向下转型。

可重复性取决于具体实现。需要两遍处理的解析器可以将一次性资源缓冲为 ByteArrayResource, 并明确设置大小限制。API 应记录它们是打开一次、重新打开、保留还是关闭流, 从而保持资源所有权明确。

主要参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)