Spring资源加载机制介绍
Resource接口定义
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();
}
Resource
集成了
InputStreamSource
接口:
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
-
getInputStream()
: 定位并打开资源,返回InputStream
用于读取资源。作为调用方必须在使用完后关闭这个流。 -
exists()
: 返回boolean
值,判断资源是否存在. -
isOpen()
: 返回boolean
值,判断当前资源是否已经在被处理,如果返回true
,InputStream
不能同时被调用,同一时间只能有一个调用者,并且必须被关闭防止资源。常规资源的实现通常返回false
。 -
getDescription()
: 通常用于处理异常时,返回该resource的说明。结果通常是返回文件的完整名称或是资源的实际URL
如果其底层实现支持的话,其他的方法则可以获取
URL
和
File
对象。
Spring本身许多需要操作资源的方法签名都是使用
Resource
接口,还有一部分Spring的API接收资源的路径,并且会根据路径的前缀自动创建合适的
Resource
对象。
尽管Spring经常使用
Resource
接口,但实际上,在自己的代码中单独使用
Resource
接口类作为通用实用工具类来访问资源非常有用,即使我们的代码不了解或不关心其他Spring的任何东西
Resource
API并没有替换任何功能,只是在相关的场景进行包装,比如,UrlResource
包装了URL
,并且实际上是使用这个URL
来进行相关操作
Spring提供的
Resource
实现
-
UrlResource
-
ClassPathResource
-
FileSystemResource
-
ServletContextResource
-
InputStreamResource
-
ByteArrayResource
UrlResource
ClassPathResource
FileSystemResource
支持处理
java.io.File
和
java.nio.file.Path
。
ServletContextResource
ServletContext资源的
Resource
实现,用于解析相关Web应用程序根目录中的相对路径。
它始终支持流访问和
URL
访问,但仅在Jar包被解压才允许
java.io.File
访问。 不管是解压还是直接访问文件系统、或者直接从JAR或其他类似数据库访问,取决于Servlet容器。
InputStreamResource
适用于给定的
InputStream
,应该被用于未指定的
Resource
的情况下进行适配。通常情况下
isOpen()
返回
true
,意味着不能多次读取流。
ByteArrayResource
将会创建一个
ByteArrayResource
基于给定的字节数组,比使用
InputStreamResource
更有效。
ResourceLoader
接口
ResourceLoader
接口需要被那些能够加载资源的对象实现:
public interface ResourceLoader {
Resource getResource(String location);
}
所有的
ApplicationContext
都实现了
ResourceLoader
接口,因此可以被用来获取相关的
Resource
实例。
更具具体的
ApplicationContext
实现类,通常不需要加资源路径的前缀,比如通过
ClassPathXmlApplicationContext
加载:
public void loadresource(){
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
}
如果需要强制使用类路径加载则也可以指定路径前缀
classpath:
public void loadresource(){
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
}
同样的,指定使用
UrlResource
需要指定
file
或
http
前缀:
public void loadresource(){