相对标准 url 访问机制,spring 的 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();
}
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
Resource 接口里的最重要的几个方法:
getInputStream()
: 定位并且打开当前资源,返回当前资源的InputStream
。预计每一次调用都会返回一个新的InputStream
,因此关闭当前输出流就成为了调用者的责任。exists()
: 返回一个boolean
,表示当前资源是否真的存在。isOpen()
: 返回一个boolean
,表示当前资源是否一个已打开的输入流。如果结果为true
,返回的InputStream
不能多次读取,只能是一次性读取之后,就关闭InputStream
,以防止内存泄漏。除了InputStreamResource
,其他常用 Resource 实现都会返回false
。getDescription()
: 返回当前资源的描述,当处理资源出错时,资源的描述会用于错误信息的输出。一般来说,资源的描述是一个完全限定的文件名称,或者是当前资源的真实 url。
Resource 接口里的其他方法可以让你获得代表当前资源的 URL
或 File
对象(前提是底层实现可兼容的,也支持该功能)。
在 spring 里,Resource
抽象有着相当广泛的使用,比如,当需要一个资源时,Resource 可以作为方法签名里的一个参数类型。在 spring api 中,有些方法(如各种 ApplicationContext
实现的构造函数)会直接采用普通格式的String
路径来创建合适的 Resource
,调用者也可以通过在路径里带上指定的前缀来创建特定 Resource
实现。
Resource
接口(实现)不仅可以被 spring 大量的应用,其也非常适合作为你编程中访问资源的辅助工具类。当你仅需要使用到 Resource 接口实现时,可以直接忽略 spring 的其余部分。单独使用 Rsourece 实现,会造成代码与 spring 的部分耦合,可也仅耦合了其中一小部分辅助类,而且你可以将 Reource 实现作为 URL 的一种访问底层更为有效的替代,与你引入其他库来达到这种目的是一样的。
需要注意的是Resource
实现并没有去重新发明轮子,而是尽可能地采用封装。举个例子,UrlResource
里就封装了一个 URL 对象,在其内的逻辑就是通过封装的 URL 对象
来完成的。