Spring Resources
Spring 提供了多种方法访问各种资源文件。
Resource 接口
相对标准 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();
}
Resource 接口里的最重要的几个方法:
getInputStream()
- 定位并且打开当前资源,返回当前资源的InputStream
。exists()
- 返回一个 boolean,表示当前资源是否真的存在。isOpen()
- 返回一个 boolean,表示当前资源是否是一个已打开的输入流。getDescription()
- 返回当前资源的描述,当处理资源出错时,资源的描述会用于错误信息的输出。一般来说,资源的描述是一个完全限定的文件名称,或者是当前资源的真实 url。
内置的 Resource 实现
spring 直接提供了多种开箱即用的 Resource 实现。
UrlResource
- UrlResource 封装了一个 java.net.URL 对象,用来访问 URL 可以正常访问的任意对象,比如文件、an HTTP target, an FTP target, 等等。ClassPathResource
- ClassPathResource 可以从类路径上加载资源,其可以使用线程上下文加载器、指定加载器或指定的 class 类型中的任意一个来加载资源。FileSystemResource
- 这是针对 java.io.File 提供的 Resource 实现。ServletContextResource
- 这是为了获取 web 根路径的 ServletContext 资源而提供的 Resource 实现。InputStreamResource
- 这是针对 InputStream 提供的 Resource 实现。ByteArrayResource
- 这是针对字节数组提供的 Resource 实现。可以通过一个字节数组来创建 ByteArrayResource。
ResourceLoader 接口
ResourceLoader
接口是用来加载 Resource 对象的。
public interface ResourceLoader {
Resource getResource(String location);
}
spring 里所有的 ApplicationContext
都实现了 ResourceLoader
接口,因此,所有 ApplicationContext
都可以通过 getResource()
方法获取 Resource
实例。
示例:
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
下表列举了 spring 根据各种位置路径加载资源的策略:
前缀 | 例子 | 解释 |
---|---|---|
classpath: | classpath:com/myapp/config.xml | 从类路径加载 |
file: | file:///data/config.xml | 以 URL 形式从文件系统加载 |
http: | http://myserver/logo.png | 以 URL 形式加载 |
(none) | /data/config.xml | 由底层的 ApplicationContext 实现决定 |
ResourceLoaderAware 接口
ResourceLoaderAware
是一个特殊的标记接口,用来标记提供 ResourceLoader
引用的对象。
public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}
当将一个 ResourceLoaderAware
接口的实现类部署到应用上下文时(此类会作为一个 spring 管理的 bean), 应用上下文会识别出此为一个 ResourceLoaderAware
对象,并将自身作为一个参数来调用 setResourceLoader()
函数,如此,该实现类便可使用 ResourceLoader 获取 Resource 实例来加载你所需要的资源。
资源依赖
如果 bean 本身将通过某种动态过程来确定和提供资源路径,那么 bean 可以使用 ResourceLoader 接口来加载资源。
请看如下 xml 示例:
<bean id="myBean" class="...">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
请注意,配置中引用的模板资源路径没有前缀,因为应用程序上下文本身将用作 ResourceLoader,资源本身将通过 ClassPathResource,FileSystemResource 或 ServletContextResource(根据需要)加载,具体取决于上下文的确切类型。
如果需要强制使用特定的资源类型,则可以使用前缀。 以下两个示例显示如何强制使用 ClassPathResource 和 UrlResource(后者用于访问文件系统文件)。
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
应用上下文和资源路径
构造应用上下文
spring 中的 ApplicationContext 的构造器通常可以使用字符串或字符串数组所指代的(多个)资源(如 xml 文件)来构造当前上下文。
示例:
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class);
使用通配符构造应用上下文
ApplicationContext 构造器的中的资源路径可以是单一的路径(即一对一地映射到目标资源);也可以是通配符形式——可包含 classpath*:也可以是前缀或 ant 风格的正则表达式(使用 spring 的 PathMatcher 来匹配)。
示例:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
使用 classpath*
表示类路径下所有匹配文件名称的资源都会被获取(本质上就是调用了 ClassLoader.getResources(…) 方法),接着将获取到的资源组装成最终的应用上下文。
在位置路径的其余部分,classpath*:
前缀可以与 PathMatcher 结合使用,如:classpath*:META-INF/*-beans.xml
。
示例代码
我的示例代码地址:spring-tutorial-core-resouces