• Spring Resource


    1:资源访问

      在Sun所提供的标准API里,资源访问通常由Java.net.URL和文件IO来完成,如果需要访问来自网络的资源时,则通常会选择URL类。

      Url类可以处理一些常规的资源访问问题,但是依然不能很好地满足所有底层资源访问的需要,比如,暂时还无法在类加载路径或相对于ServletContext的路径中访问资源,也无法检查所指向的资源是否存在。

      Spring对其内部使用到的资源实现了自己的抽象结构:Resource接口来封装底层资源。

      InputStreamSource封装任何能返回InputStream的类,比如File,Classpath下的资源和Byte Array等。它只有一个方法定义:getInputStream(),该方法返回一个新的InputStream对象。

      Resource接口本身没有提供访问任何底层资源的实现逻辑,针对不同的底层资源,Spring将会提供不同的Resource实现类,不同的实现类负责不同的资源访问逻辑。

      Spring的Resource设计是一种典型的策略模式,通过使用Resource接口,客户端程序可以在不同的资源访问策略之间自由切换。

    package org.springframework.core.io;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public interface InputStreamSource {
    
        InputStream getInputStream() throws IOException;
    
    }
    package org.springframework.core.io;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URI;
    import java.net.URL;
    
    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(); }

    2:Resource实现类

      UrlResource:访问网络资源的实现类

      ClassPathResource:访问类加载路径里资源的实现类

      FileSystemResource:访问文件系统里资源的实现类

      ServletContextResource:访问相对于ServletContext路径下的资源的实现类

      InputStreamResource:访问输入流资源的实现类

      ByteArrayResouce:访问字节数组资源的实现类

      1)UrlResource

      file:用于访问文件系统,  http:用于通过HTTP协议访问资源,  ftp:用于通过FTP协议访问资源

    package org.springframework.core.io;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.net.URL;
    import java.net.URLConnection;
    
    import org.springframework.util.Assert;
    import org.springframework.util.ResourceUtils;
    import org.springframework.util.StringUtils;
    
    public class UrlResource extends AbstractFileResolvingResource {
    
        private final URI uri;
    
        private final URL url;
    
        private final URL cleanedUrl;
    
        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());
        }
    
        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;
        }
    
        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);
        }
    
        public UrlResource(String protocol, String location) throws MalformedURLException  {
            this(protocol, location, null);
        }
    
        
        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;
            }
        }
    
        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;
            }
        }
    
        @Override
        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;
            }
        }
    
        
        @Override
        public URL getURL() throws IOException {
            return this.url;
        }
    
        
        @Override
        public URI getURI() throws IOException {
            if (this.uri != null) {
                return this.uri;
            }
            else {
                return super.getURI();
            }
        }
    
        @Override
        public File getFile() throws IOException {
            if (this.uri != null) {
                return super.getFile(this.uri);
            }
            else {
                return super.getFile();
            }
        }
    
        @Override
        public Resource createRelative(String relativePath) throws MalformedURLException {
            if (relativePath.startsWith("/")) {
                relativePath = relativePath.substring(1);
            }
            return new UrlResource(new URL(this.url, relativePath));
        }
    
    
        @Override
        public String getFilename() {
            return new File(this.url.getFile()).getName();
        }
    
        @Override
        public String getDescription() {
            return "URL [" + this.url + "]";
        }
    
        @Override
        public boolean equals(Object obj) {
            return (obj == this ||
                (obj instanceof UrlResource && this.cleanedUrl.equals(((UrlResource) obj).cleanedUrl)));
        }
    
        @Override
        public int hashCode() {
            return this.cleanedUrl.hashCode();
        }
    
    }

      2)ClassPathResource

            public ClassPathResource(String path) {
            this(path, (ClassLoader) null);
        }
    
        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());
        }
         
        public final ClassLoader getClassLoader() {
            return (this.clazz != null ? this.clazz.getClassLoader() : this.classLoader);
        }
    
        @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;
        }

      3)FileSystemResource

        public FileSystemResource(String path) {
            Assert.notNull(path, "Path must not be null");
            this.file = new File(path);
            this.path = StringUtils.cleanPath(path);
        }
    
        @Override
        public InputStream getInputStream() throws IOException {
            return new FileInputStream(this.file);
        }

      4)ByteArrayResource

        public ByteArrayResource(byte[] byteArray) {
            this(byteArray, "resource loaded from byte array");
        }
    
    
        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(this.byteArray);
        }

    分析:

      通过Resource,我们需要获取输入流InupStream,FileSystemResource和ByteArrayResource的getInputStream()方法更好理解。

      以UrlResource举例:

    通常会传进来一个String,比如说file:D://zhao.txt    

    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);
    }

    我们需要用到getCleanUrl(this.url,path)

    private URL getCleanedUrl(URL originalUrl, String originalPath) {
      try {
        return new URL(StringUtils.cleanPath(originalPath));
      }
      catch (MalformedURLException ex) {
        return originalUrl;
      }
    }

    我们的目的是把传入的String拆开,得到 : 前的内容,告诉我们用什么协议,得到 : 后的内容,告诉我们位置在哪

        public static String cleanPath(String path) {
            if (path == null) {
                return null;
            }
            String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);
    
            // Strip prefix from path to analyze, to not treat it as part of the
            // first path element. This is necessary to correctly parse paths like
            // "file:core/../core/io/Resource.class", where the ".." should just
            // strip the first "core" directory while keeping the "file:" prefix.
            int prefixIndex = pathToUse.indexOf(":");
            String prefix = "";
            if (prefixIndex != -1) {
                prefix = pathToUse.substring(0, prefixIndex + 1);
                if (prefix.contains("/")) {
                    prefix = "";
                }
                else {
                    pathToUse = pathToUse.substring(prefixIndex + 1);
                }
            }
            if (pathToUse.startsWith(FOLDER_SEPARATOR)) {
                prefix = prefix + FOLDER_SEPARATOR;
                pathToUse = pathToUse.substring(1);
            }
    
            String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);
            List<String> pathElements = new LinkedList<String>();
            int tops = 0;
    
            for (int i = pathArray.length - 1; i >= 0; i--) {
                String element = pathArray[i];
                if (CURRENT_PATH.equals(element)) {
                    // Points to current directory - drop it.
                }
                else if (TOP_PATH.equals(element)) {
                    // Registering top path found.
                    tops++;
                }
                else {
                    if (tops > 0) {
                        // Merging path element with element corresponding to top path.
                        tops--;
                    }
                    else {
                        // Normal path element found.
                        pathElements.add(0, element);
                    }
                }
            }
    
            // Remaining top paths need to be retained.
            for (int i = 0; i < tops; i++) {
                pathElements.add(0, TOP_PATH);
            }
    
            return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR);
        }
  • 相关阅读:
    linux 常用命令
    博客园兼容手机端
    博客园点击页面,显示句子
    win10 系统禁止自动更新
    php获取数组中第一个元素或最后一个元素
    设计模式
    高并发抢购
    mySql 数据库优化
    3dMax+VR的安装步骤
    3dmax
  • 原文地址:https://www.cnblogs.com/zhao307/p/5398459.html
Copyright © 2020-2023  润新知