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 提供丰富的工具封装了底层的技术,但是有点过度封装了,最终的核心其实就那么多。
 
原文地址:https://www.cnblogs.com/conge/p/5383722.html