概述

虽然JDK提供了访问资源的类如java.net.URL,File等,但是并不能很好的满足各底层访问资源的需求,如:并没有直接提供类路径或者web上下文资源的访问类。鉴于此Spring提供了访问资源的Resource接口,它为应用提供了访问底层资源的能力。Resource在Spring中起着不可或缺的作用,Spring框架通过Resource来加载各种资源,如配置文件资源、国际化属性资源等。而且Spring的Resource还可以脱离框架来使用,我们只需要引入Spring的core jar包即可使用这些功能。

Resource只是个接口,它和其实现类的结构如下:

spring启动时加载到本地缓存 spring加载资源文件_spring启动时加载到本地缓存

常用到的一些实现类介绍:

ByteArrayResource:访问二进制数组表示的资源。

ClassPathResource:访问类路径下的资源,这个是比较常用的。

FileSystemResource:访问系统资源。

InputStreamResource:访问一个InputStreamResource资源。

UrlResource:封装了java.net.URL使用户能够访问任何以URL表示的资源。

一个简单实例,这里只是引用了Spring的core jar包,并没有使用整个Spring框架:


package cn.qing.spring.resource;

import java.io.IOException;
import java.util.Properties;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.FileCopyUtils;

public class TestSpringResource {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		//使用ClassPathResource来加载类路劲下的资源
		Resource classPathResource = new ClassPathResource("resource.properties");
		//使用FileSystemResource来加载系统文件资源
		Resource fileSystemResource = new FileSystemResource("F:/myEclipseProject/spring/WebRoot/WEB-INF/classes/resource.properties");
		Properties properties = new Properties();
		try {
			System.out.println("***************************classPathResource*************************");
			properties.load(classPathResource.getInputStream());
			System.out.println("host:"+properties.getProperty("host") + "\t port:"+properties.getProperty("port")+"\t context:"+properties.getProperty("context", "default"));
			properties.clear();
			
			System.out.println("****************************fileSystemResource************************");
			properties.load(fileSystemResource.getInputStream());
			System.out.println("host:"+properties.getProperty("host") + "\t port:"+properties.getProperty("port")+"\t context:"+properties.getProperty("context", "default"));
			
			System.out.println("****************************readXml************************");
			classPathResource = new ClassPathResource("xmlresource.xml");
			//对资源进行编码
			EncodedResource encodedResource = new EncodedResource(classPathResource,"UTF-8");
			//使用FileCopyUtils.copyToString获取资源文件中的内容
			String content = FileCopyUtils.copyToString(encodedResource.getReader());
			System.out.println(content);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

其中resource.properties和xmlresource.xml都是放在src下的资源。


输出结果:


***************************classPathResource*************************
host:192.168.0.1	 port:8080	 context:spring
****************************fileSystemResource************************
host:192.168.0.1	 port:8080	 context:spring
****************************readXml************************
<?xml version="1.0" encoding="UTF-8"?>
<xml-body>
	<beans>
		<bean id="test" class="cn.qing.java.Test"/> 
	</beans>
</xml-body>



上面使用ClassPathResource和FileSystemResource都可以正常访问到我们需要的资源,像这种访问不同的资源,都必须需要使用不同的Resource资源类,才能够正常访问对应的资源。其实Spring还提供了一个强大的资源加载机制,可以通过"classpath:"、"file:"等资源地址前缀来访问资源,这种访问方式还支持通配符的方式。

Spring提供的资源地址前缀:

classpath: 用于加载类路径资源

使用形式如:classpath:cn/qing/java/bean.xml

加载类路径资源,classpath: 和 classpath:/ 是等价的,都是相对于类的根路径。资源文件可以在项目系统中,也可以在jar或zip的类包中包含,使用这种方式,都是可以正常访问。

file: 访问文件系统资源

使用形式如:file:d:/resource/test.xml

http:// 访问web服务器资源

使用形式:http://www.spring.org/test.xml 使用UrlResource类从web服务器加载资源

ftp://  访问ftp服务器资源

使用形式: ftp://www.spring.org/test.xml


以上这几种资源前缀访问都支持通配符的形式进行访问,支持3中通配符:

?  匹配文件名中的一个字符

*  匹配文件名中的任意字符

** 匹配多层路径

示例:

classpath:/cn/qing/te?t.xml  用来匹配cn/qing/test.xml或cn/qing/teot.xml等文件

classpath:/cn/qing/*.xml  用来匹配cn/qing/下所有以xml后缀的资源文件

classpath:/cn/**/test.xml 用来匹配cn/目录及其子孙目录下的所有test.xml资源文件


如何使用前缀指定的资源地址来访问资源,Spring提供了一个标准实现类PathMatchingResourcePatternResolver用来访问资源。

实例如下:


package cn.qing.spring.resource;

import java.io.IOException;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

public class TestPatternResolver {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//使用Spring提供的PathMatchingResourcePatternResolver实现类可以根据一个资源地址加载资源文件
		ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();		
		try {
			//得到匹配的所有资源
			Resource[] resources = patternResolver.getResources("classpath:/*resource.*");
			
			for(Resource rs : resources)
			{
				System.out.println("resource fileName:"+rs.getFilename());				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}



输出结果:


resource fileName:resource.properties
resource fileName:xmlresource.xml



根据结果可以看到,Spring可以正常获取这种通配符定义的资源。

ps:在使用PathMatchingResourcePatternResolver时Spring会用到LogFactory对象,所以我们需要引入commons-logging.jar包,程序才能正常运行。