Spring 学习笔记 Resource 资源

Spring Resources


概述

在日常程序开发中,处理外部资源是很繁琐的事情,我们可能需要处理 URL 资源、File 资源、ClassPath相关资源等等。并且在 java 中 Java .net.URL 类和用于各种 URL 前缀的标准处理程序对于所有对底层资源的访问都不够充分。处理各种各样的资源需要使用到不同的接口,这就增加了系统的复杂性。

对此 Spring 提供了 Resource 接口来统一这些底层资源一致的访问。Resource 接口是一个更强大的接口,用于抽象对底层资源的访问。

public interface Resource extends InputStreamSource {

    boolean exists();

    boolean isOpen();

    URL getURL() throws IOException;

    File getFile() throws IOException;

    Resource createRelative(String relativePath) throws IOException;

    String getFilename();

    String getDescription();

}

Resource 继承了 InputStreamSource 下面是 InputStreamSource 的内容

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

方法解析

  1. getInputStream():每次调用都会返回一个与资源对应的 InputStream 字节流,调用者有必要在使用后关闭该资源。
  2. exists():返回 true 表示当前资源存在。
  3. isOpen():返回 Resource 代表的资源是否已经被打开。如果返回 true,则只能读取一次不能多次读取 InputStream,然后关闭,以避免资源泄漏。对于所有常见的 Resource 实现一般返回 false。
  4. getURL():返回 Resource 代表资源对应的 java.util.URL 对象。
  5. getFile():返回 Resource 代表资源对应的 java.io.File 对象。
  6. createRelative(String relativePath):用于创建相对于当前 Resource 代表资源的资源,比如当前 Resource 代表文件资源 “d:/test/” 则 createRelative(“test.txt”) 将返回表文件资源 “d:/test/test.txt” Resource 资源。
  7. getFilename():返回 Resource 代表资源对应的文件路径。
  8. getDescription():返回 Resource 代表资源的描述符,通常就是资源的全路径(实际文件名或实际 URL 地址)。

Spring 框架自身就非常广泛使用 Resource,在我们的项目中也可以使用并且可以非常方便的获取到目标资源。

内置 Resource 接口实现

  1. UrlResource
  2. ClassPathResource
  3. FileSystemResource
  4. ServletContextResource
  5. InputStreamResource
  6. ByteArrayResource

UrlResource
UrlResource 封装了 java.net.URL,可用于访问通过 URL 访问的任何对象,比如文件、HTTP 资源、FTP 资源等等。所有 URL 都有一个标准化的字符串表示,因此可以使用适当的标准化前缀来表示不同 URL 类型的 URL。一般支持如下资源访问。

  1. file:用于访问文件系统路径
new UrlResource("file:d/xxx.txt");
  1. http:用于通过 http 协议访问资源
new UrlResource("http://地址");
  1. ftp: 用于通过 ftp 访问资源
new UrlResource("ftp://地址");

ClassPathResource
ClassPathResource 表示从类路径获取资源,它使用线程上下文类加载器、给定的类加载器来加载资源。classpath 资源存在于类路径中的文件系统中或 jar 包里。

ClassPathResource 常用构造器

public ClassPathResource(String path);
public ClassPathResource(String path, @Nullable ClassLoader classLoader);
public ClassPathResource(String path, @Nullable Class<?> clazz);
  1. public ClassPathResource(String path):使用默认的类加载器记载 path 类路径下的资源
  2. public ClassPathResource(String path, @Nullable ClassLoader classLoader):使用指定的类加载器加载 path 类路径下的资源
  3. public ClassPathResource(String path, @Nullable Class clazz):只用指定的类加载 path 类路径下的资源

FileSystemResource
FileSystemResource 是 Resource 实现支持 java.io 和 java.nio.file.Path 的处理。

ServletContextResource
ServletContextResource 是 web 应用资源,ServletContext 资源的实现。用于简化 servlet 容器的 ServletContext 接口的 getResource 操作和 getResourceAsStream 操作。

InputStreamResource
InputStreamResource 是基于 InputStream 的实现,参数是一个 InputStream 只有在没有特定场景下的 Resource 的时候才使用它。

public InputStreamResource(InputStream inputStream);
public InputStreamResource(InputStream inputStream, @Nullable String description);

ByteArrayResource
ByteArrayResource 是给定一个 byte[] 数组的实现创建 ByteArrayInputStream。

ResourceLoader

ResourceLoader 用于返回 Resource 的实例。

public interface ResourceLoader {
    Resource getResource(String location);
}

Spring 的 ApplicationContext 都实现了 ResourceLoader

  1. ClassPathXmlApplicationContext
  2. FileSystemXmlApplicationContext
  3. WebApplicationContext

因此可以使用 ApplicationContext 来获取资源实例,当在某个 ApplicationContext 实现类中调用 getResource 而参数没有指定特定的资源前缀时,将返回适合 ApplicationContext 实现实例的资源类型,下面是 ClassPathXmlApplicationContext 的执行代码

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");

对于 ClassPathXmlApplicationContext 以上代码返回一个 ClassPathResource。
如果对 FileSystemXmlApplicationContext 实例执行相同的方法,它将返回FileSystemResource。对于 WebApplicationContext,它将返回一个 ServletContextResource。

另外也可以指定资源前缀比如 classpath: 强制使用 ClassPathResource 无论 ApplicationContext 实现实例类型是什么。

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");

也可以使用其他前缀

Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");

getResource 字符串参数对象转换为资源对象的策略

资源前缀 示例 说明
classpath: classpath:com/myapp/config.xml 从 classpath 类路径加载
file: file:///data/config.xml 从文件系统中作为 URL 加载
http: https://myserver/logo.png 作为 URL 加载
(none) /data/config.xml 根据 ApplicationContext 实现实例加载

ResourceLoaderAware
ResourceLoaderAware 接口是一个特殊的回调接口,通过对应的 ApplicationContext 注入。

public interface ResourceLoaderAware {
    void setResourceLoader(ResourceLoader resourceLoader);
}

当一个类实现 ResourceLoaderAware 接口时,Spring IoC 容器在加载该 bean 的时候将该 bean 类型识别为 ResourceLoaderAware 然后调用对应的 setResourceLoader(ResourceLoader resourceLoader) 方法并将 ApplicationContext 的实例的 getResource 方法返回实例传递进去

ApplicationContext 构建

ApplicationContext 的构建通常将字符串或字符串数组作为资源的位置路径。当字符串参数路径没有前缀时,加载 bean 的 Resource 实例依赖于 ApplicationContext 的实例。例如,考虑下面的例子,它创建了一个 ClassPathXmlApplicationContext:

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

appContext.xml 文件里的 bean 都是从类路径加载的,因为使用了 Classpathresource。

ApplicationContext 构建的通配符
构建 ApplicationContext 的参数路径可以是精确的路径 classpath:conf/appContext.xml 每个路径都有到目标资源的一对一映射。或者也可以包含特殊的字符 classpath*: 这种机制的一个用途是,当您需要进行依赖式的应用程序组装时。并且当使用以classpath*: 作为前缀的相同路径创建最终的 ApplicationContext 时,所有依赖包 classpath 都会自动被获取。

classpath 和 classpath* 区别

  1. classpath:用于加载类路径(包括jar包)中的一个且仅一个资源;对于多个匹配的也只返回一个。
  2. classpath* :用于加载类路径(包括jar包)中的所有匹配的资源。

注意:用 classpath*: 需要遍历所有的 classpath,所以加载效率会比较差一些尽量少使用。

posted @ 2019-06-13 17:16  一定要细心  阅读(534)  评论(0编辑  收藏  举报