0
点赞
收藏
分享

微信扫一扫

【Spring(十五)】Resource


Java中处理资源的核心接口是InputStream和OutputStream,但是用起来不是特别方便,spring在此基础上做了进一步的封装,形成了以Resource接口为核心的一套资源体系。

首先看下Resource接口:

public interface Resource extends InputStreamSource {

boolean exists();

boolean isReadable();

boolean isOpen();

URL getURL() throws IOException;

URI getURI() throws IOException;

File getFile() throws IOException;

long contentLength() throws IOException;

long lastModified() throws IOException;

Resource createRelative(String relativePath) throws IOException;

String getFilename();

String getDescription();

}

对于不同类型的资源,其实现是不同的,比如处理classpath下的资源就和处理文件系统下的资源方式不同。但是其行为都可以统一抽象为上面的接口。

下面分别看几个调用的例子:

Properties properties1 = new Properties();
Resource r1 = new ClassPathResource("a.properties");
properties1.load(r1.getInputStream());
System.out.println(properties1.getProperty("name"));

Resource r2 = new FileSystemResource("/Users/miracle/Desktop/1.properties");
Properties properties2 = new Properties();
properties2.load(r2.getInputStream());
System.out.println(properties2.getProperty("name"));

Resource r3 = new UrlResource("http://localhost:8080/test");
System.out.println(IOUtils.toString(r3.getInputStream(), "utf-8"));

分别是基于classpath、文件系统以及网络url的三种实现。对于读取而言,都是先构造一个Resource实例,然后拿到其内部的InputStream,然后读取。

 

其实,基于上面的方式,已经可以比较容易的获取资源了,但是spring提供了更加强大的功能,ResourceLoader接口:

public interface ResourceLoader {

/** Pseudo URL prefix for loading from the class path: "classpath:" */
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

Resource getResource(String location);

ClassLoader getClassLoader();

}

通过一个ResourceLoader接口实例,我们可以无需关心Resource具体的实现类型,只要按照ResourceLoader的约定传入不同的资源路径,ResourceLoader会根据资源路径的格式做出相应的判断,查找对应类型的资源。

该接口的默认实现是DefaultResourceLoader,可以看下其getResource方法的实现:

public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// Try to parse the location as a URL...
URL url = new URL(location);
return new UrlResource(url);
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}

首先判定传入的路径参数是否以“classpath:”开头,如果是的话,就按照classpathresource的方式来加载资源,否则的话按照urlresource的方式加载(注意!!!该模式既可以处理files:xxx格式的文件资源,也可以处理url的),如果还不行,仍然以classpath的方式解析。

如上方式是不支持ant风格的路径的,也就是一次只能匹配一个资源。所以,spring中常用的是其子接口:ResourcePatternResolver

该接口增加了Ant风格的资源路径,可以返回多个。实现类为:PathMatchingResourcePatternResolver。

classpath*:xxx

classpath:xxx

前者可以匹配classpath下所有符合条件的资源,后者只能匹配一个。

另外,也可以在路径中加入通配符:

如files:/*/a.txt等。

关于Ant路径,这里就不详述了,可以参考:​​javascript:void(0)​​ ?:一个字符

*:任意0或多个字符

**:任意0或多级目录

最后看下其核心方法:

public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
// a class path resource (multiple resources for same name possible)
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
// a class path resource pattern
return findPathMatchingResources(locationPattern);
}
else {
// all class path resources with the given name
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
// Only look for a pattern after a prefix here
// (to not get fooled by a pattern symbol in a strange prefix).
int prefixEnd = locationPattern.indexOf(":") + 1;
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
// a file pattern
return findPathMatchingResources(locationPattern);
}
else {
// a single resource with the given name
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}

 

 

 

举报

相关推荐

0 条评论