在 Spring 的核心源码中,Resource
接口定义了 Spring 对底层资源访问的抽象,通过实现 Resource 接口,我们可以开发各种资源的访问能力。以 Spring 自身为例,Resource
的使用非常广泛,我们可以在源码中的很多方法或者构造方法中看到 Resource
类型的参数。比如,通过 XML 加载容器配置、从 application.properties 文件读取 Spring Boot 项目配置信息,都是通过 Resource 接口的实现类来实现对这些文件的访问的。
Resource
接口
Resource
接口的定义如下:
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
boolean isFile();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
ReadableByteChannel readableChannel() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
在以上的方法中:
exist()
和isXXX()
方法提供了对资源状态的判断;getFile()
、getURI()
和getURL()
提供了资源到File
、URI
、URL
的转换;getFilename()
、getDescription()
提供了一些资源信息的获取,一般用于日志信息。
此外,它还继承了 InputStreamSource
接口:
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
这里的 getInputStream()
提供了从资源获取输入流的方法,每次调用这个方法,都需要返回一个新的输入流,不过要注意,输入流不在被使用的时候,一定要记得关闭。
Resource
实现类
在 Spring 中,已经包含了很多 Resource
的实现类,如下是一些常见的 Resource
实现类:
从这些实现类的名称中,我们就能看出它们分别实现了那些来源的资源访问。下面我们分别分析一下这几个实现类:
FileSystemResource
一个 FileSystemResource
可以通过 File 对象或者文件路径来创建,在 FileSystemResource
类中,有以下三个成员变量:
private final String path;
@Nullable
private final File file;
private final Path filePath;
它们会在构造方法中被初始化,值分别是文件路径字符串、访问文件的 File
对象、文件路径对应的 Path
对象。
当调用 getInputStream()
方法的时候,会通过 File 对象创建一个 InputStream
对象。其他的一些操作也都会在 File 对象上完成。
ByteArrayResource
从 ByteArrayResource
的名字就可以看出,创建它并不需要外部资源,只需要提供一个 ByteArray
即可。在 ByteArrayResource
中只有两个成员变量:
private final byte[] byteArray;
private final String description;
分别代表 byteArray 本身和其描述信息,我们可以在创建对象时给它提供一个描述,如果不提供,默认的描述信息是 resource loaded from byte array
,当需要调用 getInputStream()
获取输入流的时候,将会得到一个 ByteArrayInputStream
。实现方法如下:
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.byteArray);
}
ByteArrayResource
比较适用于一些需要用 ByteArray
创建一次性输入流的地方。
UrlResource
UrlResource
可以使用 URL
创建,也可以使用 URI
创建,可以用来访问一些需要通过 HTTP 或者 FTP 等访问的文件和内容。
当调用 getInputStream()
方法获取数据流的时候,会通过 URL
创建 URLConnection
,然后从中获取 InputStream
对象,代码如下:
@Override
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
try {
return con.getInputStream();
}
catch (IOException ex) {
// Close the HTTP connection (if applicable).
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).disconnect();
}
throw ex;
}
}
ClassPathResource
ClassPathResource
提供了从类路径访问资源的方法,创建 ClassPathResource
需要提供一个资源路径,以及一个类加载器或者一个类对象。我们通常在 Spring 的配置文件中使用 classpath:
作为前缀的资源路径,都是通过 ClassPathResource
读取的。
InputStreamResource
我们也可以使用 InputStreamResource
将一个已经创建的 InputStream
封装成一个 Resource
,当通过 getInputStream()
获取输入流的时候,会得到我们创建 InputStreamResource
时提供的 InputStream
。当没有其他的 Resource
实现类可以适用当前资源的时候,可以使用它,不过,这个资源的数据流只能被读取一次。