欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring resource

程序员文章站 2022-07-15 13:05:39
...

spring resource

Spring资源抽象Resource,JDK操纵底层资源基本就是 java.net.URL 、java.io.File 、java.util.Properties,取资源基本是根据绝对路径或当前类的相对路径来取。从类路径或Web容器上下文中获取资源的时候也不方便。Resource接口提供了更强大的访问底层资源的能力。
spring resource

Resouce 接口

直接继承了JDK的InputStream,看源码

package org.springframework.core.io;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import org.springframework.core.io.InputStreamSource;

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 var1) throws IOException; //相对的路径下创建一个文件

    String getFilename();

    String getDescription();
}

抽象类AbstractResource

Convenience base class for {@link Resource} implementations,pre-implementing typical behavior.对于任何的接口而言,这个直接抽象类是重中之重,里面浓缩了接口的大部分公共实现,其中大量的使用了模板方法模式,留给子类去实现这些具体的资源对应的处理的方式。

public abstract class AbstractResource implements Resource {
    public AbstractResource() {
    }

    public boolean exists() {
        try {
            return this.getFile().exists(); //子类获取getFile
        } catch (IOException var4) {
            try {
                InputStream isEx = this.getInputStream(); //获取流,还是没有不存在哦
                isEx.close();//可能有的资源只有流信息,没有文件信息,比如http路径
                return true;
            } catch (Throwable var3) {
                return false;
            }
        }
    }

    public boolean isReadable() {
        return true;
    }

    public boolean isOpen() {
        return false;
    }

    public URL getURL() throws IOException { //留给子类去特定的实现
        throw new FileNotFoundException(this.getDescription() + " cannot be resolved to URL");
    }

    public URI getURI() throws IOException {
        URL url = this.getURL();

        try {
            return ResourceUtils.toURI(url);
        } catch (URISyntaxException var3) {
            throw new NestedIOException("Invalid URI [" + url + "]", var3);
        }
    }

    public File getFile() throws IOException {//留给子类去实现
        throw new FileNotFoundException(this.getDescription() + " cannot be resolved to absolute file path");
    }

    public long contentLength() throws IOException { //计算长度哦
        InputStream is = this.getInputStream();
        Assert.state(is != null, "resource input stream must not be null");

        try {
            long size = 0L;

            int read;
            for(byte[] buf = new byte[255]; (read = is.read(buf)) != -1; size += (long)read) {
                ;
            }

            long var6 = size;
            return var6;
        } finally {
            try {
                is.close();
            } catch (IOException var14) {
                ;
            }

        }
    }

    public long lastModified() throws IOException {
        long lastModified = this.getFileForLastModifiedCheck().lastModified();
        if(lastModified == 0L) {
            throw new FileNotFoundException(this.getDescription() + " cannot be resolved in the file system for resolving its last-modified timestamp");
        } else {
            return lastModified;
        }
    }

    protected File getFileForLastModifiedCheck() throws IOException {
        return this.getFile();
    }

    public Resource createRelative(String relativePath) throws IOException { //创建相对路径下的文件夹的信息,由子类去实现
        throw new FileNotFoundException("Cannot create a relative resource for " + this.getDescription());
    }

    public String toString() {
        return this.getDescription();
    }

    public boolean equals(Object obj) {
        return obj == this || obj instanceof Resource && ((Resource)obj).getDescription().equals(this.getDescription());
    }

}

Resource的子接口的信息ContextResource and WritableResource

WritableResource:添加当前的类是否可写,获取当前文件的输出流信息
ContextResource:获取上下文路径
1 ContextResource添加了一个接口

  public interface ContextResource extends Resource {

    /**
     * Return the path within the enclosing 'context'.
     * <p >This is typically path relative to a context-specific root directory,
     * e.g. a ServletContext root or a PortletContext root.
     */
    String getPathWithinContext(); //获取上下文的路径的信息

  }  

2 WritableResource判断当前文件的可写

public interface WritableResource extends Resource {
    boolean isWritable();

    OutputStream getOutputStream() throws IOException;//获取输出流的信息
}

重要的抽象类AbstractFileResolvingResource

这个抽象类继承自AbstractResource,重写了AbstractResource的大部分方法。resolve URLs into File references!将URL类型的文件进行转换。

/**
 * Abstract base class for resources which resolve URLs into File references,
 * such as {@link UrlResource} or {@link ClassPathResource}.
 *
 * <p>Detects the "file" protocol as well as the JBoss "vfs" protocol in URLs,
 * resolving file system references accordingly.
 *
 * @author Juergen Hoeller
 * @since 3.0
 */
public abstract class AbstractFileResolvingResource extends AbstractResource {

    /**
     * This implementation returns a File reference for the underlying class path
     * resource, 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 { //  通过资源的URL得到资源本身
        URL url = getURL();
        if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            return VfsResourceDelegate.getResource(url).getFile();
        }
        return ResourceUtils.getFile(url, getDescription());
    }

    /**
     * This implementation determines the underlying File
     * (or jar file, in case of a resource in a jar/zip).
     */
    @Override
    protected File getFileForLastModifiedCheck() throws IOException { //内部使用
        URL url = getURL();
        if (ResourceUtils.isJarURL(url)) {
            URL actualUrl = ResourceUtils.extractJarFileURL(url);
            if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
                return VfsResourceDelegate.getResource(actualUrl).getFile();
            }
            return ResourceUtils.getFile(actualUrl, "Jar URL");
        }
        else {
            return getFile();
        }
    }

    /**
     * This implementation returns a File reference for the underlying class path
     * resource, provided that it refers to a file in the file system.
     * @see org.springframework.util.ResourceUtils#getFile(java.net.URI, String)
     */
    protected File getFile(URI uri) throws IOException { //  通过资源uri获取文件
        if (uri.getScheme().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            return VfsResourceDelegate.getResource(uri).getFile();
        }
        return ResourceUtils.getFile(uri, getDescription());
    }


    @Override
    public boolean exists() { //判断资源是否存在,如果是文件Url,直接获取文件判断,否则,建立连接来判断。
        try {
            URL url = getURL();
            if (ResourceUtils.isFileURL(url)) {
                // Proceed with file system resolution...
                return getFile().exists();
            }
            else {
                // Try a URL connection content-length header...
                URLConnection con = url.openConnection();
                customizeConnection(con);
                HttpURLConnection httpCon =
                        (con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
                if (httpCon != null) {
                    int code = httpCon.getResponseCode();
                    if (code == HttpURLConnection.HTTP_OK) {
                        return true;
                    }
                    else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
                        return false;
                    }
                }
                if (con.getContentLength() >= 0) {
                    return true;
                }
                if (httpCon != null) {
                    // no HTTP OK status, and no content-length header: give up
                    httpCon.disconnect();
                    return false;
                }
                else {
                    // Fall back to stream existence: can we open the stream?
                    InputStream is = getInputStream();
                    is.close();
                    return true;
                }
            }
        }
        catch (IOException ex) {
            return false;
        }
    }

    @Override
    public boolean isReadable() { //  是否可读
        try {
            URL url = getURL();
            if (ResourceUtils.isFileURL(url)) {
                // Proceed with file system resolution...
                File file = getFile();
                return (file.canRead() && !file.isDirectory());
            }
            else {
                return true;
            }
        }
        catch (IOException ex) {
            return false;
        }
    }

    @Override
    public long contentLength() throws IOException {
        URL url = getURL();
        if (ResourceUtils.isFileURL(url)) {
            // Proceed with file system resolution...
            return getFile().length();
        }
        else {
            // Try a URL connection content-length header...
            URLConnection con = url.openConnection();
            customizeConnection(con);
            return con.getContentLength();
        }
    }

    @Override
    public long lastModified() throws IOException {
        URL url = getURL();
        if (ResourceUtils.isFileURL(url) || ResourceUtils.isJarURL(url)) {
            // Proceed with file system resolution...
            return super.lastModified();
        }
        else {
            // Try a URL connection last-modified header...
            URLConnection con = url.openConnection();
            customizeConnection(con);
            return con.getLastModified();
        }
    }


    /**
     * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.
     */
    private static class VfsResourceDelegate {

        public static Resource getResource(URL url) throws IOException {
            return new VfsResource(VfsUtils.getRoot(url));
        }

        public static Resource getResource(URI uri) throws IOException {
            return new VfsResource(VfsUtils.getRoot(uri));
        }
    }

}

jar URL地址解读
URL URI 的区别
[scheme:]scheme-specific-part[#fragment]

相关标签: spring resource