Spring的资源抽象Resource2实体类
阅读原文时间:2023年07月17日阅读:1

aaarticlea/png;base64,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" alt="" name="" />

一、文件系统资源 FileSystemResource

  文件系统资源 FileSystemResource,资源以文件系统路径的方式表示,唯一一个实现了WritableResource接口的类。这个类由2个不可变的属性 file 和 path ,本质上就是一个java.io.File 的包装。这个类的 equals() 和 hashcode() 都通过属性 path 来操作。

public class FileSystemResource extends AbstractResource implements WritableResource {

private final File file;   //  不可变属性

private final String path; //  不可变属性

public FileSystemResource(File file) { //  简单的构造方法,path为file路径格式化后的样子  
    Assert.notNull(file, "File must not be null");  
    this.file = file;  
    this.path = StringUtils.cleanPath(file.getPath());  
}

public FileSystemResource(String path) {   //简单的构造方法  
    Assert.notNull(path, "Path must not be null");  
    this.file = new File(path);  
    this.path = StringUtils.cleanPath(path);  
}

public final String getPath() {    //新增的方法,返回资源路径,方法不可重写  
    return this.path;  
}

@Override  
public boolean exists() {  
    return this.file.exists();  
}

@Override  
public boolean isReadable() {  
    return (this.file.canRead() && !this.file.isDirectory());  
}

public InputStream getInputStream() throws IOException {   //InputStreamSource接口的实现方法  
    return new FileInputStream(this.file);  
}

@Override  
public URL getURL() throws IOException {   //可见这个url是通过uri得到的  
    return this.file.toURI().toURL();  
}

@Override  
public URI getURI() throws IOException {  
    return this.file.toURI();  
}

@Override  
public File getFile() {  
    return this.file;  
}

@Override  
public long contentLength() throws IOException {  
    return this.file.length();  
}

@Override  
public Resource createRelative(String relativePath) {  
    String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);  
    return new FileSystemResource(pathToUse);  
}

@Override  
public String getFilename() {  
    return this.file.getName();  
}

public String getDescription() {   //  资源描述,直接用绝对路径来构造  
    return "file \[" + this.file.getAbsolutePath() + "\]";  
}

public boolean isWritable() {  //  WritableResource接口的实现方法  
    return (this.file.canWrite() && !this.file.isDirectory());  
}

public OutputStream getOutputStream() throws IOException {  
    return new FileOutputStream(this.file);  
}

@Override  
public boolean equals(Object obj) {    //通过path来比较  
    return (obj == this ||  
        (obj instanceof FileSystemResource && this.path.equals(((FileSystemResource) obj).path)));  
}

@Override  
public int hashCode() {    //  文件资源的HashCode就是path的hashCode  
    return this.path.hashCode();  
}

}

二、常用的ClassPathResource

ClassPathResource这个资源类表示的是类路径下的资源,资源以相对于类路径的方式表示,是基于class的 getResourceAsStream(this.path) 或者 this.classLoader.getResourceAsStream(this.path) 。

public class ClassPathResource extends AbstractFileResolvingResource {

private final String path;

private ClassLoader classLoader;

private Class<?> clazz;

/\*\*  
 \* Create a new ClassPathResource for ClassLoader usage.  
 \* A leading slash will be removed, as the ClassLoader  
 \* resource access methods will not accept it.  
 \* <p>The thread context class loader will be used for  
 \* loading the resource.  
 \* @param path the absolute path within the class path  
 \* @see java.lang.ClassLoader#getResourceAsStream(String)  
 \* @see org.springframework.util.ClassUtils#getDefaultClassLoader()  
 \*/  
public ClassPathResource(String path) {  
    this(path, (ClassLoader) null);  
}

/\*\*  
 \* Create a new ClassPathResource for ClassLoader usage.  
 \* A leading slash will be removed, as the ClassLoader  
 \* resource access methods will not accept it.  
 \* @param path the absolute path within the classpath  
 \* @param classLoader the class loader to load the resource with,  
 \* or {@code null} for the thread context class loader  
 \* @see ClassLoader#getResourceAsStream(String)  
 \*/  
public ClassPathResource(String path, ClassLoader classLoader) {  
    Assert.notNull(path, "Path must not be null");  
    String pathToUse = StringUtils.cleanPath(path);  
    if (pathToUse.startsWith("/")) {  
        pathToUse = pathToUse.substring(1);  
    }  
    this.path = pathToUse;  
    this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());  
}

/\*\*  
 \* Create a new ClassPathResource for Class usage.  
 \* The path can be relative to the given class,  
 \* or absolute within the classpath via a leading slash.  
 \* @param path relative or absolute path within the class path  
 \* @param clazz the class to load resources with  
 \* @see java.lang.Class#getResourceAsStream  
 \*/  
public ClassPathResource(String path, Class<?> clazz) {  
    Assert.notNull(path, "Path must not be null");  
    this.path = StringUtils.cleanPath(path);  
    this.clazz = clazz;  
}

/\*\*  
 \* Create a new ClassPathResource with optional ClassLoader and Class.  
 \* Only for internal usage.  
 \* @param path relative or absolute path within the classpath  
 \* @param classLoader the class loader to load the resource with, if any  
 \* @param clazz the class to load resources with, if any  
 \*/  
protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {  
    this.path = StringUtils.cleanPath(path);  
    this.classLoader = classLoader;  
    this.clazz = clazz;  
}

/\*\*  
 \* Return the path for this resource (as resource path within the class path).  
 \*/  
public final String getPath() {  
    return this.path;  
}

/\*\*  
 \* Return the ClassLoader that this resource will be obtained from.  
 \*/  
public final ClassLoader getClassLoader() {  
    return (this.classLoader != null ? this.classLoader : this.clazz.getClassLoader());  
}

/\*\*  
 \* This implementation checks for the resolution of a resource URL.  
 \* @see java.lang.ClassLoader#getResource(String)  
 \* @see java.lang.Class#getResource(String)  
 \*/  
@Override  
public boolean exists() {  
    URL url;  
    if (this.clazz != null) {  
        url = this.clazz.getResource(this.path);  
    }  
    else {  
        url = this.classLoader.getResource(this.path);  
    }  
    return (url != null);  
}

/\*\*  
 \* This implementation opens an InputStream for the given class path resource.  
 \* @see java.lang.ClassLoader#getResourceAsStream(String)  
 \* @see java.lang.Class#getResourceAsStream(String)  
 \*/  
public InputStream getInputStream() throws IOException {  
    InputStream is;  
    if (this.clazz != null) {  
        is = this.clazz.getResourceAsStream(this.path);  
    }  
    else {  
        is = this.classLoader.getResourceAsStream(this.path);  
    }  
    if (is == null) {  
        throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");  
    }  
    return is;  
}

/\*\*  
 \* This implementation returns a URL for the underlying class path resource.  
 \* @see java.lang.ClassLoader#getResource(String)  
 \* @see java.lang.Class#getResource(String)  
 \*/  
@Override  
public URL getURL() throws IOException {  
    URL url;  
    if (this.clazz != null) {  
        url = this.clazz.getResource(this.path);  
    }  
    else {  
        url = this.classLoader.getResource(this.path);  
    }  
    if (url == null) {  
        throw new FileNotFoundException(getDescription() + " cannot be resolved to URL because it does not exist");  
    }  
    return url;  
}

/\*\*  
 \* This implementation creates a ClassPathResource, applying the given path  
 \* relative to the path of the underlying resource of this descriptor.  
 \* @see org.springframework.util.StringUtils#applyRelativePath(String, String)  
 \*/  
@Override  
public Resource createRelative(String relativePath) {  
    String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);  
    return new ClassPathResource(pathToUse, this.classLoader, this.clazz);  
}

/\*\*  
 \* This implementation returns the name of the file that this class path  
 \* resource refers to.  
 \* @see org.springframework.util.StringUtils#getFilename(String)  
 \*/  
@Override  
public String getFilename() {  
    return StringUtils.getFilename(this.path);  
}

/\*\*  
 \* This implementation returns a description that includes the class path location.  
 \*/  
public String getDescription() {  
    StringBuilder builder = new StringBuilder("class path resource \[");  
    String pathToUse = path;  
    if (this.clazz != null && !pathToUse.startsWith("/")) {  
        builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));  
        builder.append('/');  
    }  
    if (pathToUse.startsWith("/")) {  
        pathToUse = pathToUse.substring(1);  
    }  
    builder.append(pathToUse);  
    builder.append('\]');  
    return builder.toString();  
}

/\*\*  
 \* This implementation compares the underlying class path locations.  
 \*/  
@Override  
public boolean equals(Object obj) {  
    if (obj == this) {  
        return true;  
    }  
    if (obj instanceof ClassPathResource) {  
        ClassPathResource otherRes = (ClassPathResource) obj;  
        return (this.path.equals(otherRes.path) &&  
                ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&  
                ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));  
    }  
    return false;  
}

/\*\*  
 \* This implementation returns the hash code of the underlying  
 \* class path location.  
 \*/  
@Override  
public int hashCode() {  
    return this.path.hashCode();  
}

}

三、Url资源——UrlResource

UrlResource这个资源类封装了可以以URL表示的各种资源。这个资源类有3个属性,一个URI、一个URL,以及一个规范化后的URL,用于资源间的比较以及计算HashCode。

public class UrlResource extends AbstractFileResolvingResource {

/\*\*  
 \* Original URI, if available; used for URI and File access.  
 \*/  
private final URI uri;

/\*\*  
 \* Original URL, used for actual access.  
 \*/  
private final URL url;

/\*\*  
 \* Cleaned URL (with normalized path), used for comparisons.  
 \*/  
private final URL cleanedUrl;

/\*\*  
 \* Create a new UrlResource based on the given URI object.  
 \* @param uri a URI  
 \* @throws MalformedURLException if the given URL path is not valid  
 \*/  
public UrlResource(URI uri) throws MalformedURLException {  
    Assert.notNull(uri, "URI must not be null");  
    this.uri = uri;  
    this.url = uri.toURL();  
    this.cleanedUrl = getCleanedUrl(this.url, uri.toString());  
}

/\*\*  
 \* Create a new UrlResource based on the given URL object.  
 \* @param url a URL  
 \*/  
public UrlResource(URL url) {  
    Assert.notNull(url, "URL must not be null");  
    this.url = url;  
    this.cleanedUrl = getCleanedUrl(this.url, url.toString());  
    this.uri = null;  
}

/\*\*  
 \* Create a new UrlResource based on a URL path.  
 \* <p>Note: The given path needs to be pre-encoded if necessary.  
 \* @param path a URL path  
 \* @throws MalformedURLException if the given URL path is not valid  
 \* @see java.net.URL#URL(String)  
 \*/  
public UrlResource(String path) throws MalformedURLException {  
    Assert.notNull(path, "Path must not be null");  
    this.uri = null;  
    this.url = new URL(path);  
    this.cleanedUrl = getCleanedUrl(this.url, path);  
}

/\*\*  
 \* Create a new UrlResource based on a URI specification.  
 \* <p>The given parts will automatically get encoded if necessary.  
 \* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);  
 \* also known as "scheme"  
 \* @param location the location (e.g. the file path within that protocol);  
 \* also known as "scheme-specific part"  
 \* @throws MalformedURLException if the given URL specification is not valid  
 \* @see java.net.URI#URI(String, String, String)  
 \*/  
public UrlResource(String protocol, String location) throws MalformedURLException  {  
    this(protocol, location, null);  
}

/\*\*  
 \* Create a new UrlResource based on a URI specification.  
 \* <p>The given parts will automatically get encoded if necessary.  
 \* @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);  
 \* also known as "scheme"  
 \* @param location the location (e.g. the file path within that protocol);  
 \* also known as "scheme-specific part"  
 \* @param fragment the fragment within that location (e.g. anchor on an HTML page,  
 \* as following after a "#" separator)  
 \* @throws MalformedURLException if the given URL specification is not valid  
 \* @see java.net.URI#URI(String, String, String)  
 \*/  
public UrlResource(String protocol, String location, String fragment) throws MalformedURLException  {  
    try {  
        this.uri = new URI(protocol, location, fragment);  
        this.url = this.uri.toURL();  
        this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString());  
    }  
    catch (URISyntaxException ex) {  
        MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());  
        exToThrow.initCause(ex);  
        throw exToThrow;  
    }  
}

/\*\*  
 \* Determine a cleaned URL for the given original URL.  
 \* @param originalUrl the original URL  
 \* @param originalPath the original URL path  
 \* @return the cleaned URL  
 \* @see org.springframework.util.StringUtils#cleanPath  
 \*/  
private URL getCleanedUrl(URL originalUrl, String originalPath) {  
    try {  
        return new URL(StringUtils.cleanPath(originalPath));  
    }  
    catch (MalformedURLException ex) {  
        // Cleaned URL path cannot be converted to URL  
        // -> take original URL.  
        return originalUrl;  
    }  
}

/\*\*  
 \* This implementation opens an InputStream for the given URL.  
 \* It sets the "UseCaches" flag to {@code false},  
 \* mainly to avoid jar file locking on Windows.  
 \* @see java.net.URL#openConnection()  
 \* @see java.net.URLConnection#setUseCaches(boolean)  
 \* @see java.net.URLConnection#getInputStream()  
 \*/  
public InputStream getInputStream() throws IOException {  
    URLConnection con = this.url.openConnection();  
    ResourceUtils.useCachesIfNecessary(con);  
    try {  
        return con.getInputStream();  
    }  
    catch (IOException ex) {  
        // Close the HTTP connection (if applicable).  
        if (con instanceof HttpURLConnection) {  
            ((HttpURLConnection) con).disconnect();  
        }  
        throw ex;  
    }  
}

/\*\*  
 \* This implementation returns the underlying URL reference.  
 \*/  
@Override  
public URL getURL() throws IOException {  
    return this.url;  
}

/\*\*  
 \* This implementation returns the underlying URI directly,  
 \* if possible.  
 \*/  
@Override  
public URI getURI() throws IOException {  
    if (this.uri != null) {  
        return this.uri;  
    }  
    else {  
        return super.getURI();  
    }  
}

/\*\*  
 \* This implementation returns a File reference for the underlying URL/URI,  
 \* provided that it refers to a file in the file system.  
 \* @see org.springframework.util.ResourceUtils#getFile(java.net.URL, String)  
 \*/  
@Override  
public File getFile() throws IOException {  
    if (this.uri != null) {  
        return super.getFile(this.uri);  
    }  
    else {  
        return super.getFile();  
    }  
}

/\*\*  
 \* This implementation creates a UrlResource, applying the given path  
 \* relative to the path of the underlying URL of this resource descriptor.  
 \* @see java.net.URL#URL(java.net.URL, String)  
 \*/  
@Override  
public Resource createRelative(String relativePath) throws MalformedURLException {  
    if (relativePath.startsWith("/")) {  
        relativePath = relativePath.substring(1);  
    }  
    return new UrlResource(new URL(this.url, relativePath));  
}

/\*\*  
 \* This implementation returns the name of the file that this URL refers to.  
 \* @see java.net.URL#getFile()  
 \* @see java.io.File#getName()  
 \*/  
@Override  
public String getFilename() {  
    return new File(this.url.getFile()).getName();  
}

/\*\*  
 \* This implementation returns a description that includes the URL.  
 \*/  
public String getDescription() {  
    return "URL \[" + this.url + "\]";  
}

/\*\*  
 \* This implementation compares the underlying URL references.  
 \*/  
@Override  
public boolean equals(Object obj) {  
    return (obj == this ||  
        (obj instanceof UrlResource && this.cleanedUrl.equals(((UrlResource) obj).cleanedUrl)));  
}

/\*\*  
 \* This implementation returns the hash code of the underlying URL reference.  
 \*/  
@Override  
public int hashCode() {  
    return this.cleanedUrl.hashCode();  
}

}

四、Servlet上下文资源——ServletContextResource

实现基本就是基于 this.servletContext.getResource(this.path) 或 this.servletContext.getResourceAsStream(this.path) 这两个方法。

public class ServletContextResource extends AbstractFileResolvingResource implements ContextResource {

private final ServletContext servletContext;

private final String path;

/\*\*  
 \* Create a new ServletContextResource.  
 \* <p>The Servlet spec requires that resource paths start with a slash,  
 \* even if many containers accept paths without leading slash too.  
 \* Consequently, the given path will be prepended with a slash if it  
 \* doesn't already start with one.  
 \* @param servletContext the ServletContext to load from  
 \* @param path the path of the resource  
 \*/  
public ServletContextResource(ServletContext servletContext, String path) {  
    // check ServletContext  
    Assert.notNull(servletContext, "Cannot resolve ServletContextResource without ServletContext");  
    this.servletContext = servletContext;

    // check path  
    Assert.notNull(path, "Path is required");  
    String pathToUse = StringUtils.cleanPath(path);  
    if (!pathToUse.startsWith("/")) {  
        pathToUse = "/" + pathToUse;  
    }  
    this.path = pathToUse;  
}

/\*\*  
 \* Return the ServletContext for this resource.  
 \*/  
public final ServletContext getServletContext() {  
    return this.servletContext;  
}

/\*\*  
 \* Return the path for this resource.  
 \*/  
public final String getPath() {  
    return this.path;  
}

/\*\*  
 \* This implementation checks {@code ServletContext.getResource}.  
 \* @see javax.servlet.ServletContext#getResource(String)  
 \*/  
@Override  
public boolean exists() {  
    try {  
        URL url = this.servletContext.getResource(this.path);  
        return (url != null);  
    }  
    catch (MalformedURLException ex) {  
        return false;  
    }  
}

/\*\*  
 \* This implementation delegates to {@code ServletContext.getResourceAsStream},  
 \* which returns {@code null} in case of a non-readable resource (e.g. a directory).  
 \* @see javax.servlet.ServletContext#getResourceAsStream(String)  
 \*/  
@Override  
public boolean isReadable() {  
    InputStream is = this.servletContext.getResourceAsStream(this.path);  
    if (is != null) {  
        try {  
            is.close();  
        }  
        catch (IOException ex) {  
            // ignore  
        }  
        return true;  
    }  
    else {  
        return false;  
    }  
}

/\*\*  
 \* This implementation delegates to {@code ServletContext.getResourceAsStream},  
 \* but throws a FileNotFoundException if no resource found.  
 \* @see javax.servlet.ServletContext#getResourceAsStream(String)  
 \*/  
public InputStream getInputStream() throws IOException {  
    InputStream is = this.servletContext.getResourceAsStream(this.path);  
    if (is == null) {  
        throw new FileNotFoundException("Could not open " + getDescription());  
    }  
    return is;  
}

/\*\*  
 \* This implementation delegates to {@code ServletContext.getResource},  
 \* but throws a FileNotFoundException if no resource found.  
 \* @see javax.servlet.ServletContext#getResource(String)  
 \*/  
@Override  
public URL getURL() throws IOException {  
    URL url = this.servletContext.getResource(this.path);  
    if (url == null) {  
        throw new FileNotFoundException(  
                getDescription() + " cannot be resolved to URL because it does not exist");  
    }  
    return url;  
}

/\*\*  
 \* This implementation resolves "file:" URLs or alternatively delegates to  
 \* {@code ServletContext.getRealPath}, throwing a FileNotFoundException  
 \* if not found or not resolvable.  
 \* @see javax.servlet.ServletContext#getResource(String)  
 \* @see javax.servlet.ServletContext#getRealPath(String)  
 \*/  
@Override  
public File getFile() throws IOException {  
    URL url = this.servletContext.getResource(this.path);  
    if (url != null && ResourceUtils.isFileURL(url)) {  
        // Proceed with file system resolution...  
        return super.getFile();  
    }  
    else {  
        String realPath = WebUtils.getRealPath(this.servletContext, this.path);  
        return new File(realPath);  
    }  
}

/\*\*  
 \* This implementation creates a ServletContextResource, applying the given path  
 \* relative to the path of the underlying file of this resource descriptor.  
 \* @see org.springframework.util.StringUtils#applyRelativePath(String, String)  
 \*/  
@Override  
public Resource createRelative(String relativePath) {  
    String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);  
    return new ServletContextResource(this.servletContext, pathToUse);  
}

/\*\*  
 \* This implementation returns the name of the file that this ServletContext  
 \* resource refers to.  
 \* @see org.springframework.util.StringUtils#getFilename(String)  
 \*/  
@Override  
public String getFilename() {  
    return StringUtils.getFilename(this.path);  
}

/\*\*  
 \* This implementation returns a description that includes the ServletContext  
 \* resource location.  
 \*/  
public String getDescription() {  
    return "ServletContext resource \[" + this.path + "\]";  
}

public String getPathWithinContext() {  
    return this.path;  
}

/\*\*  
 \* This implementation compares the underlying ServletContext resource locations.  
 \*/  
@Override  
public boolean equals(Object obj) {  
    if (obj == this) {  
        return true;  
    }  
    if (obj instanceof ServletContextResource) {  
        ServletContextResource otherRes = (ServletContextResource) obj;  
        return (this.servletContext.equals(otherRes.servletContext) && this.path.equals(otherRes.path));  
    }  
    return false;  
}

/\*\*  
 \* This implementation returns the hash code of the underlying  
 \* ServletContext resource location.  
 \*/  
@Override  
public int hashCode() {  
    return this.path.hashCode();  
}

}

五、其它不常用的实现类

1、字节数组资源——ByteArrayResource

    若需要操作描述一个字节数组,可以用这个资源类。ByteArrayResource可多次读取数组资源。

2、描述性资源——DescriptiveResource

 若一个资源,仅仅有一个描述,非常抽象的这种情况,可以用这个资源类,它并没有指向一个实际的可读的资源。

3、输入流资源——InputStreamResource

 输入流资源InputStreamResource,是一个不可变InputStream的包装和一个不可变的描述字符串。此外还有一个私有成员变量Boolean read用于限制本资源的InputStream不可被重复获取。这个包装类指向的是一个已经打开的资源,所以它的 isOpen()总是返回true。而且它不能重复获取资源,只能读取一次

4、VFS资源——VfsResource

    vfs是Virtual File System虚拟文件系统,也称为虚拟文件系统开关(Virtual Filesystem Switch).是Linux档案系统对外的接口。任何要使用档案系统的程序都必须经由这层接口来使用它。(摘自百度百科…)它能一致的访问物理文件系统、jar资源、zip资源、war资源等,VFS能把这些资源一致的映射到一个目录上,访问它们就像访问物理文件资源一样,而其实这些资源不存在于物理文件系统。

5、Portlet上下文资源——PortletContextResource

    Portlet是基于java的web组件,由portlet容器管理,并由容器处理请求,生产动态内容。这个资源类封装了一个不可变的javax.portlet.PortletContext对象和一个不可变的String对象代表路径。类中所有操作都基于这两个属性。PortletContextResource对象实现了ContextResource接口,实现了方法String getPathWithinContext(),即返回自身的path属性。

http://www.cnblogs.com/zrtqsk/p/4015985.html