Resource介绍
编码的时候,除了代码本身,我们还需要对外部的资源进行处理。例如:URL资源、URI资源、File资源、ClassPath相关资源、服务器相关资源(VFS等)等等。
而这些资源的处理是类似而繁琐的,如:打开资源、读取资源、关闭资源。
所以Spring提供了一个专门的接口Resource 用于统一这些底层资源的访问。
就是说,Spring的Resource接口代表底层外部资源,提供了对底层外部资源的一致性访问接口。
源码如下:
public interface InputStreamSource { InputStream getInputStream() throws IOException; } 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(); }
Resource接口提供了足够的抽象,足够满足我们日常使用。而且提供了很多内置Resource实现:ByteArrayResource、InputStreamResource 、FileSystemResource 、UrlResource 、ClassPathResource、ServletContextResource、VfsResource等。
ByteArrayResource代表byte[]数组资源,对于 getInputStream() 操作将返回一个ByteArrayInputStream。ByteArrayResource可多次读取数组资源,即 isOpen() 永远返回false。 InputStreamResource代表java.io.InputStream字节流,对于getInputStream() 操作将直接返回该字节流,因此只能读取一次该字节流,即 isOpen() 永远返回true。 FileSystemResource代表java.io.File资源,对于 getInputStream() 操作将返回底层文件的字节流,isOpen() 将永远返回false,从而表示可多次读取底层文件的字节流。
ClassPathResource代表classpath路径的资源,将使用ClassLoader进行加载资源。classpath 资源存在于类路径中的文件系统中或jar包里,且 isOpen() 永远返回false,表示可多次读取资源。 ClassPathResource加载资源替代了Class类和ClassLoader类的getResource(String name)和getResourceAsStream(String name)两个加载类路径资源方法,提供一致的访问方式。 ClassPathResource提供了三个构造器: public ClassPathResource(String path):使用默认的ClassLoader加载“path”类路径资源; public ClassPathResource(String path, ClassLoader classLoader):使用指定的ClassLoader加载“path”类路径资源; -- 比如当前类路径是“cn.javass.spring.chapter4.ResourceTest”,而需要加载的资源路径是“cn/javass/spring/chapter4/test1.properties”,则将加载的资源在“cn/javass/spring/chapter4/test1.properties”; public ClassPathResource(String path, Class<?> clazz):使用指定的类加载“path”类路径资源,将加载相对于当前类的路径的资源; -- 比如当前类路径是“cn.javass.spring.chapter4.ResourceTest”,而需要加载的资源路径是“cn/javass/spring/chapter4/test1.properties”,则将加载的资源在“cn/javass/spring/chapter4/cn/javass/spring/chapter4/test1.properties”;
-- 而如果需要 加载的资源路径为“test1.properties”,将加载的资源为“cn/javass/spring/chapter4/test1.properties”。
-- 需要注意一定:资源查找顺序是先查找当前类路径的资源,再去查找jar包,而且,只要找到就会返回。
-- 如果是在jar包中的资源,需要使用getURL(),而不是getFile(),因为资源不是存在于File系统,而是存在于jar包中!!!
UrlResource代表URL资源,用于简化URL资源访问。“isOpen”永远返回false,表示可多次读取资源。
UrlResource一般支持如下资源访问:
http:通过标准的http协议访问web资源,如new UrlResource(“http://地址”);
ftp:通过ftp协议访问资源,如new UrlResource(“ftp://地址”);
file:通过file协议访问本地文件系统资源,如new UrlResource(“file:d:/test.txt”);
ServletContextResource代表web应用资源,用于简化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作;
VfsResource代表Jboss 虚拟文件系统资源。
Resource访问
ResourceLoader接口用于返回Resource对象;其实现可以看作是一个生产Resource的工厂类。
public interface ResourceLoader { Resource getResource(String location); ClassLoader getClassLoader(); }
getResource接口用于根据提供的location参数返回相应的Resource对象;而getClassLoader则返回加载这些Resource的ClassLoader。
Spring提供了一个适用于所有环境的DefaultResourceLoader实现,可以返回ClassPathResource、UrlResource;
还提供一个用于web环境的ServletContextResourceLoader,它继承了DefaultResourceLoader的所有功能,又额外提供了获取ServletContextResource的支持。
ResourceLoader在进行加载资源时需要使用前缀来指定需要加载:“classpath:path”表示返回ClasspathResource,“http://path”和“file:path”表示返回UrlResource资源;如果不加前缀则需要根据当前上下文来决定;另外,DefaultResourceLoader默认实现可以加载classpath资源。
目前所有的ApplicationContext都实现了ResourceLoader,因此可以使用其来加载资源。
ClassPathXmlApplicationContext:不指定前缀将返回默认的ClassPathResource资源,否则将根据前缀来加载资源; FileSystemXmlApplicationContext:不指定前缀将返回FileSystemResource,否则将根据前缀来加载资源; WebApplicationContext:不指定前缀将返回ServletContextResource,否则将根据前缀来加载资源; 其他:不指定前缀根据当前上下文返回Resource实现,否则将根据前缀来加载资源。
ResourceLoader
ResourceLoaderAware是一个标记接口,用于通过ApplicationContext注入ResourceLoader。
注入Resource
通过注入来获取ResourceLoader,再来访问资源,很麻烦!!!
Spring提供了ResourceEditor(这是一个PropertyEditor),用于在注入的字符串和Resource之间进行转换。
因此可以使用注入方式注入Resource。
package cn.javass.spring.chapter4.bean; import org.springframework.core.io.Resource; public class ResourceBean3 { private Resource resource; public Resource getResource() { return resource; } public void setResource(Resource resource) { this.resource = resource; } }
<bean id="resourceBean1" class="cn.javass.spring.chapter4.bean.ResourceBean3"> <property name="resource" value="cn/javass/spring/chapter4/test1.properties"/> </bean> <bean id="resourceBean2" class="cn.javass.spring.chapter4.bean.ResourceBean3"> <property name="resource" value="classpath:cn/javass/spring/chapter4/test1.properties"/> </bean>
注意此处“resourceBean1”注入的路径没有前缀表示根据使用的ApplicationContext实现进行选择Resource实现。
Resource通配符路径
Spring提供了一种更强大的Ant模式通配符匹配,能匹配一批资源。
Ant路径通配符支持“?”、“*”、“**”,注意通配符匹配不包括目录分隔符“/”: “?”:匹配一个字符,如“config?.xml”将匹配“config1.xml”; “*”:匹配零个或多个字符串,如“cn/*/config.xml”将匹配“cn/javass/config.xml”,但不匹配匹配“cn/config.xml”;而“cn/config-*.xml”将匹配“cn/config-dao.xml”; “**”:匹配路径中的零个或多个目录,如“cn/**/config.xml”将匹配“cn /config.xml”,也匹配“cn/javass/spring/config.xml”;而“cn/javass/config-**.xml”将匹配“cn/javass/config-dao.xml”,即把“**”当做两个“*”处理。
小结:
① Spring通过Resource接口统一访问外部资源,并提供了一堆实现类,可以分别访问File、classpath、URL、URI等等资源。
② Spring通过ResourceLoader接口获取Resource。
③ ApplicationContext都实现了ResourceLoader接口,所以可以直接加载资源!
④ 实现ResourceLoaderAware接口,可以注入ResourceLoader。
⑤ 注入Resource。
⑥ Resource通配符路径。
声明:源自张开涛的Spring教程,稍作加工。