资源抽象接口
回顾
- ClassLoader 加载资源:
ClassLoader.getResourceAsStream()
,从 ClassPath 根路径下获取。而且路径不能以’/’ 开头
- Class 类加载资源:
Class.getResourceAsStream(String path)
-
path
不以 /
开头,就是针对当前的类,是从此类所在的包下取资源
-
path
以 /
开头,则是从 ClassPath 下获取资源
- ServletContext 加载资源:
servletContext.getResourceAsStream(String path)
,默认从 Web 应用根目录下取资源,path
建议加上/
Resource 接口及其实现
Resource 接口
-
org.springframework.core.io.Resource
实现了 InputStreamSource
接口。InputStreamSource
是 Spring
资源加载的基础接口,定义了InputStream getInputStream()
方法,用于获取文件的InputStream
流,调用这个方法都会得到一个新的流。在 JavaMail 的附件等场景使用。
-
Resource
接口在 Spring 中负责装载各种资源,包括文件资源、外部文件资源、国际化属性文件等,并且可以脱离 Spring 单独使用。统一的Resource
接口可以使用EncodedResource
进行编码,以保证内容操作的正确性
- 该接口的部分主要方法,如下
方法 |
描述 |
boolean exists(); |
资源是否存在 |
boolean isReadable(); |
资源是否可读 |
boolean isOpen(); |
资源是否打开 |
URL getURL() |
如果底层资源可以表示成URL,这该方法返回对应的URL对象 |
File getFile() |
如果底层资源对应一个文件,这该方法返回对应File对象 |
InputStream getInputStream() |
返回资源对应的输入流 |
-
Resource
接口的主要实现
实现类 |
描述 |
WritableResource |
可写资源接口。主要有FileSystemResource和PathResource两个实现 |
FileSystemResource |
文件系统资源,如D://conf/bean/xml |
PathResource |
支持Path、Url、系统文件路径等表示的资源(spring4.x) |
InputStreamResource |
以输入流返回表示的资源 |
ByteArrayResource |
二进制数组表示的资源 |
ClassPathResource |
ClassPath 路径下的资源,相对路径存在 |
UrlResource |
通过 Url 访问资源 |
ServletContextResource |
Web上下文访问资源。负责相对于 Web 应用根目录的路径加载资源 |
- 类图如下

简单示例
-
ClassPathResource
:
ClassPathResource classPathResource = new ClassPathResource("spring-context.xml");
String filename = classPathResource.getFilename();
System.out.println("Filename: " + filename);
// spring-context.xml
String path = classPathResource.getPath();
System.out.println("Path:" + path);
// 使用 EncodedResource 对资源进行编码
EncodedResource encodedResource = new EncodedResource(classPathResource, Charset.defaultCharset());
Reader reader = encodedResource.getReader();
String s = FileCopyUtils.copyToString(reader);
System.out.println(s);
FileSystemResource
FileSystemResource fileSystemResource = new FileSystemResource("G:\\WorkSpace\\Sam\\Learning\\Learning-Spring\\spring-ioc\\src\\main\\resources\\spring-context.xml");
String filename = fileSystemResource.getFilename();
System.out.println(filename);
// G:/WorkSpace/Sam/Learning/Learning-Spring/spring-ioc/src/main/resources/spring-context.xml
String path = fileSystemResource.getPath();
System.out.println(path);
// 使用 EncodedResource 对资源进行编码
EncodedResource encodedResource = new EncodedResource(fileSystemResource, Charset.forName("UTF-8"));
Reader reader = encodedResource.getReader();
String s = FileCopyUtils.copyToString(reader);
System.out.println(s);
资源加载器
访问不同类型的资源,使用相应的 Resource 实现类,如访问ClassPath
下的资源使用ClassPathResource
,而web根路径下的资源就需要ServletContextResource
。这其实不是很方便。Spring 提供了一个强大的加载资源的机制,直接可以通过classpath:
、file:
等资源地址前缀、或者是带有Ant
风格通配符地址资源自动加载
地址资源表达式
- 资源类型的地址前缀
地址前缀 |
对应的资源类型 |
classpath: |
从类路径加载资源。classpath:和classpath:/是等价的,都是相对于类的根路径。classpath*:多个jar包中的同一个包名,全部加载 |
file: |
使用 UrlResource 装载,可采用绝对或相对路径 |
http:// |
使用 UrlResource 从web 服务器中装载 |
ftp:// |
使用 UrlResource 从FTP服务器中装载 |
无前缀 |
根据 ApplicationContext 的具体实现类采用相应类型的 Resource |
- Ant 风格的资源路径
通配符 |
描述 |
? |
匹配文件名中的一个字符 |
* |
匹配文件名中的任意字符 |
** |
匹配多层路径 |
资源加载器
- Spring 定义了一套资源加载的接口
org.springframework.core.io.ResourceLoader
,并提供实现类
资源加载器 |
描述 |
ResourceLoader |
基础接口,仅有一个 Resource getResource(String location); 方法,根据资源地址加载资源,返回 Resource |
ResourcePatternResolver |
新增了 Resource[] getResources(String locationPattern) 方法,支持类型前缀以及Ant风格的资源路径表达式 |
PathMatchingResourcePatternResolver |
Spring 提供的标准实现类。如手动加载 mybatis 的 mapperLocations |
ApplicationContext |
Spring上下文容器,其内部加载资源也是同样的机制 |
-
PathMatchingResourcePatternResolver
示例:
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 默认使用 DefaultResourceLoader.getResource()
// 1- "/" 开头,ClassPathContextResource
// 2- "classpath:"开头,ResourceUtils.CLASSPATH_URL_PREFIX封装了常量,使用 ClassPathResource
// 3- 其他使用 UrlResource
// 4- 异常(如相对地址):ClassPathContextResource
Resource resource = resolver.getResource("classpath:spring-context.xml");
EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
Reader reader = encodedResource.getReader();
String s = FileCopyUtils.copyToString(reader);
System.out.println(s);
// classpath*:不同jar包中,都有com.learning 包名,classpath加载第一个,classpath* 会加载多个
// classpath*:/mapper/**/*Mapper.xml
Resource[] resources = resolver.getResources("classpath*:spring-context.xml");

总结
Spring 提供的这套资源访问接口(Resource)与资源加载机制(ResourceLoader)是整个 Spring 容器的基础,脱离 Spring 一样非常有用
参考
- 源码地址
