spring-003-Resource资源
spring 提供一个Resource接口来统一底层资源一致的访问,而且提供了一些便利的接口
一、Resource接口
org.springframework.core.io.Resource,对InputStream进行了封装
package org.springframework.core.io; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; /** * Interface for a resource descriptor that abstracts from the actual * type of underlying resource, such as a file or class path resource. * * <p>An InputStream can be opened for every resource if it exists in * physical form, but a URL or File handle can just be returned for * certain resources. The actual behavior is implementation-specific. * @see #getInputStream() * @see #getURL() * @see #getURI() * @see #getFile() * @see WritableResource * @see ContextResource * @see FileSystemResource * @see ClassPathResource * @see UrlResource * @see ByteArrayResource * @see InputStreamResource * @see PathResource */ public interface Resource extends InputStreamSource { /** * 资源是否存在 */ boolean exists(); /** * 资源是否可读 */ boolean isReadable(); /** * 如果资源可读,返回true */ boolean isOpen(); /** * 如果是一个URL资源,则返回 */ URL getURL() throws IOException; /** * 如果是一个URI资源,则返回 */ 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的实现类
- org.springframework.core.io.ByteArrayResource 字节流的Resource
- org.springframework.core.io.FileSystemResource 文件系统的Resource
- org.springframework.core.io.ClassPathResource 基于classpath资源的Resource
- org.springframework.core.io.UrlResource URL资源
- org.springframework.core.io.ServletContextResource web应用资源
有两个实现需要特别提一下,ClassPathResource 和ServletContextResource
1、ClassPathResource
构造函数有三个:
public ClassPathResource(String path);//使用默认的ClassLoader加载资源 public ClassPathResource(String path, ClassLoader classLoader);//使用指定的ClassLoader public ClassPathResource(String path, Class<?> clazz);//使用指定Class加载资源
加载资源的方法如下:
@Override public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if (this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); } if (is == null) { throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist"); } return is; }
代码里写的非常清晰,不需要累赘叙述了。
2、ServletContextResource
ServletContextResource代表web应用资源,用于简化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作
唯一的一个构造函数,事实上则是把ServletContext依赖在对象上
public ServletContextResource(ServletContext servletContext, String path) ;
加载资源方法,还是利用了servletContext.getResourceAsStream(String path)方法
@Override public InputStream getInputStream() throws IOException { InputStream is = this.servletContext.getResourceAsStream(this.path); if (is == null) { throw new FileNotFoundException("Could not open " + getDescription()); } return is; }
二、ResourceLoader
org.springframework.core.io.ResourceLoader 接口,用来加载Resource
package org.springframework.core.io; import org.springframework.util.ResourceUtils; /** * @see Resource * @see org.springframework.core.io.support.ResourcePatternResolver * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ResourceLoaderAware */ 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 */ ClassLoader getClassLoader(); }
主要两个类实现了方法
- org.springframework.core.io.DefaultResourceLoader 默认提供,用来加载ClassPathResource,UrlResource
- org.springframework.core.io.FileSystemResourceLoader 继承自DefaultResourceLoader ,加载FileSystemResource
- org.springframework.core.io.ServletContextResourceLoader 继承自DefaultResourceLoader,加载ServletContextResource
而顶层容器ApplicationContext继承了ResourceLoader接口ApplicationContext的类,都具有加载资源的能力
三、ResourcePatternResolver
org.springframework.core.io.support.ResourcePatternResolver继承ResourceLoader
package org.springframework.core.io.support; import java.io.IOException; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public interface ResourcePatternResolver extends ResourceLoader { /** * Pseudo URL prefix for all matching resources from the class path: "classpath*:" */ String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; /** * Resolve the given location pattern into Resource objects. */ Resource[] getResources(String locationPattern) throws IOException; }
主要根据路径可以解析多个资源
实现该接口的类
- org.springframework.core.io.support.PathMatchingResourcePatternResolver 可以自动识别资源类型
- org.springframework.core.io.support.ServletContextResourcePatternResolver 继承自PathMatchingResourcePatternResolver ,添加了对web资源的识别
总结:基本上Spring Resource基础知识就这么多,事实上也是经过层层封装,最终的核心,还是File,InputStream,URI,加载的资源从文件系统,classpath,web资源, 网络上。
我想说的是,spring 提供丰富的工具封装了底层的技术,但是有点过度封装了,最终的核心其实就那么多。