一、对资源的抽象

Spring把其资源做了一个抽象,底层使用统一的资源访问接口来访问Spring的所有资源。也就是说,不管什么格式的文件,也不管文件在哪里,到Spring 底层,都只有一个访问接口,Resource。

1.1 类结构图

1.2 类和接口分析

1、可以看到有四个比较重要的接口 InputStreamSource、Resource、WritableResource、ContextResource。
a 、InputStreamSource接口

public interface InputStreamSource {/*** Return an {@link InputStream}.* <p>It is expected that each call creates a <i>fresh</i> stream.* <p>This requirement is particularly important when you consider an API such* as JavaMail, which needs to be able to read the stream multiple times when* creating mail attachments. For such a use case, it is <i>required</i>* that each {@code getInputStream()} call returns a fresh stream.* @return the input stream for the underlying resource (must not be {@code null})* @throws IOException if the stream could not be opened* @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource)*/InputStream getInputStream() throws IOException;
}

b、Resource接口
接口中定义了对于资源的判断、对资源的获取、对资源描述的获取。通过该接口可以对资源进行有效的操作。但是Resource接口注重于对资源的读取。

public interface Resource extends InputStreamSource {/*** 判断是否存在*/boolean exists();/*** 判断是否可读*/boolean isReadable();/*** Return whether this resource represents a handle with an open* stream. If true, the InputStream cannot be read multiple times,* and must be read and closed to avoid resource leaks.* <p>Will be {@code false} for typical resource descriptors.* 判断流是否可以重复读取,如果为true的话表示不可以重复读取,在读取完成后需要关闭流*/boolean isOpen();/*** Return a URL handle for this resource.* @throws IOException if the resource cannot be resolved as URL,* i.e. if the resource is not available as descriptor*/URL getURL() throws IOException;/*** Return a URI handle for this resource.* @throws IOException if the resource cannot be resolved as URI,* i.e. if the resource is not available as descriptor*/URI getURI() throws IOException;/*** Return a File handle for this resource.* @throws IOException if the resource cannot be resolved as absolute* file path, i.e. if the resource is not available in a file system*/File getFile() throws IOException;/***  资源的长度* Determine the content length for this resource.* @throws IOException if the resource cannot be resolved* (in the file system or as some other known physical resource type)*/long contentLength() throws IOException;/*** 上次更新时间* Determine the last-modified timestamp for this resource.* @throws IOException if the resource cannot be resolved* (in the file system or as some other known physical resource type)*/long lastModified() throws IOException;/*** 根据资源的当前位置,获取相对位置的其他资源* Create a resource relative to this resource.* @param relativePath the relative path (relative to this resource)* @return the resource handle for the relative resource* @throws IOException if the relative resource cannot be determined*/Resource createRelative(String relativePath) throws IOException;/*** 返回资源的名称* Determine a filename for this resource, i.e. typically the last* part of the path: for example, "myfile.txt".* <p>Returns {@code null} if this type of resource does not* have a filename.*/String getFilename();/*** 返回资源的描述* Return a description for this resource,* to be used for error output when working with the resource.* <p>Implementations are also encouraged to return this value* from their {@code toString} method.* @see Object#toString()*/String getDescription();}

C、WritableResource
因为Resource接口主要是注重对资源的读取,当我们对资源进行写入的时候,需要获取对应的判断和输出流。WritableResource接口主要定义了对写入的支持。

public interface WritableResource extends Resource {/*** 返回资源是否可以被写入*/boolean isWritable();/*** 获取资源的写入流*/OutputStream getOutputStream() throws IOException;}

D、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、存在一个AbstractResource的抽象类,所有的对于资源获取都继承自AbstractResource抽象类。

3、其余的都是具体的实现类
用来加载指定的资源

二、对资源的加载

Spring框架为了更方便的获取资源,尽量弱化程序员对各个Resource接口的实现类的感知,定义了另一个ResourceLoader接口。 接口有一个特别重要的方法:Resource getResource(String location),返回Resource实例。因此程序员在使用Spring容器时,可以不去过于计较底层Resource的实现,也不需要自己创建Resource实现类,而是直接使用ReourceLoader,获取到bean容器本身的Resource,进而取到相关的资源信息。

2.1 类继承图

2.2 类和接口分析

  1. 接口ResourceLoader和ResourcePatternResolver
    a、ResourceLoader接口
    只能对classpath路径下面的资源进行加载,并且只会加载指定的文件的
public interface ResourceLoader {/** Pseudo URL prefix for loading from the class path: "classpath:" */String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;/*** 用来根据location来获取对应的资源*/Resource getResource(String location);/*** 获取类加载器*/ClassLoader getClassLoader();}

b、ResourcePatternResolver接口
表示会加载所有路径下面的文件,包括jar包中的文件。同时locationPattern可以设置为表达式来加载对应的文件。

public interface ResourcePatternResolver extends ResourceLoader {/*** 表示会加载所有路径下面的文件,包括jar包中*/String CLASSPATH_ALL_URL_PREFIX = "classpath*:";/*** 根据*/Resource[] getResources(String locationPattern) throws IOException;}

区别
classpath: :表示从类路径中加载资源,classpath:和classpath:/是等价的,都是相对于类的根路径。资源文件库标准的在文件系统中,也可以在JAR或ZIP的类包中。

classpath:*:假设多个JAR包或文件系统类路径都有一个相同的配置文件,classpath:只会在第一个加载的类路径下查找,而classpath*:会扫描所有这些JAR包及类路径下出现的同名文件。

  1. DefaultResourceLoader
    spring实现的默认的加载器,一般其他的加载器会继承该类,并重写getResourceByPath方法
public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");// 以/开头,那么根据path去查找if (location.startsWith("/")) {return getResourceByPath(location);}// 以classpath开头,那么抽象为ClassPathResourceelse if (location.startsWith(CLASSPATH_URL_PREFIX)) {return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {// 其他情况采用UrlResource来进行加载URL url = new URL(location);return new UrlResource(url);}catch (MalformedURLException ex) {// No URL -> resolve as resource path.return getResourceByPath(location);}}}
  1. PathMatchingResourcePatternResolver
    Spring提供了一个ResourcePatternResolver实现PathMatchingResourcePatternResolver,它是基于模式匹配的,默认使用AntPathMatcher进行路径匹配,它除了支持ResourceLoader支持的前缀外,还额外支持“classpath*:”用于加载所有匹配的类路径Resource,ResourceLoader不支持前缀“classpath*:”:

三、Resource的一些工具类

3.1 工具类截图

3.2 详解

1、EncodedResource
当您使用 Resource 实现类加载文件资源时,它默认采用操作系统的编码格式。
如果文件资源采用了特殊的编码格式(如 UTF-8),则在读取资源内容时必须事先通过 EncodedResource 指定编码格式,否则将会产生中文乱码的问题。

public class EncodedResource {private final Resource resource;private final String encoding;private final Charset charset;/*** 根据encoding和charset是否存在来判断是否可以获取Reader*/public boolean requiresReader() {return (this.encoding != null || this.charset != null);}/*** 根据EncodedResource信息获取Reader信息*/public Reader getReader() throws IOException {if (this.charset != null) {return new InputStreamReader(this.resource.getInputStream(), this.charset);}else if (this.encoding != null) {return new InputStreamReader(this.resource.getInputStream(), this.encoding);}else {return new InputStreamReader(this.resource.getInputStream());}}/*** Open a {@code java.io.InputStream} for the specified resource, ignoring any* specified {@link #getCharset() Charset} or {@linkplain #getEncoding() encoding}.* @throws IOException if opening the InputStream failed* @see #requiresReader()* @see #getReader()*/public InputStream getInputStream() throws IOException {return this.resource.getInputStream();}}

2、ResourcePatternUtils

/*** Return whether the given resource location is a URL: either a* special "classpath" or "classpath*" pseudo URL or a standard URL*/public static boolean isUrl(String resourceLocation) {return (resourceLocation != null &&(resourceLocation.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX) ||ResourceUtils.isUrl(resourceLocation)));}/*** 根据ResourceLoader构建一个ResourcePatternResolver*/public static ResourcePatternResolver getResourcePatternResolver(ResourceLoader resourceLoader) {Assert.notNull(resourceLoader, "ResourceLoader must not be null");if (resourceLoader instanceof ResourcePatternResolver) {return (ResourcePatternResolver) resourceLoader;}else if (resourceLoader != null) {return new PathMatchingResourcePatternResolver(resourceLoader);}else {return new PathMatchingResourcePatternResolver();}}

3、PropertiesLoaderUtils
根据提供的Resource或者EncodedResource,将其中的内容转换为Property内容。

1、spring之Resource加载相关推荐

  1. Spring解析,加载及实例化Bean的顺序(零配置)

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 作者:jb_hz blog.csdn.net/qq_2752 ...

  2. Spring中ApplicationContext加载机制和配置初始化

    转自:http://liuwei1578.blog.163.com/blog/static/495803642007116111923195/ Spring中ApplicationContext加载机 ...

  3. 在Spring Boot中加载初始化数据

    文章目录 依赖条件 data.sql文件 schema.sql 文件 @sql注解 @SqlConfig 注解 在Spring Boot中加载初始化数据 在Spring Boot中,Spring Bo ...

  4. springboot 读取配置文件_使用 @ConfigurationProperties 在 Spring Boot 中加载配置

    本文地址: 使用 @ConfigurationProperties 在 Spring Boot 中加载配置 使用 Spring Boot 加载配置文件的配置非常便利,我们只需要使用一些注解配置一下就能 ...

  5. 深入Spring:自定义注解加载和使用

    转自:https://blog.csdn.net/z69183787/article/details/53784845 前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方 ...

  6. Spring框架如何加载和定义Spring Bean类?

    本篇介绍什么是Spring Bean类,如何创建Bean类,以及如何将Bean类添加到Spring IOC容器.通过本篇的学习,可以达成如下目标. ● 认识Spring Bean类 ● 掌握Bean类 ...

  7. Spring Boot : 资源加载器

    1.美图 2.概述 前言参考: 源码:Spring boot 主程序的功能(启动流程) ResourceLoader接口,在 Spring 中用于加载资源,通过它可以获取一个Resouce 对象.使用 ...

  8. spring 配置文件被加载两次

    如下web.xml示例: 1.用spring的配置加载contextConfigLocation 2.配置spring-mvc的contextConfigLocation <servlet> ...

  9. spring配置中加载properties文件方法

    首先,遇到一个问题,spring配置中加载properties文件配置如下: <context:property-placeholder ignore-unresolvable="tr ...

  10. Spring Boot配置加载顺序

    Spring Boot 不仅可以通过配置文件进行配置,还可以通过环境变量.命令行参数等多种形式进行配置.这些配置都可以让开发人员在不修改任何代码的前提下,直接将一套 Spring Boot 应用程序在 ...

最新文章

  1. vagrant学习笔记
  2. Java SpringMVC框架学习(二)httpServeltRequest和Model传值的区别
  3. Hadoop入门(二十三)Mapreduce的求数量最大程序
  4. sql 全角转半角_每天10分钟带你学会MySQL(二)SQL语句的基本书写规则
  5. man exportfs(exportfs命令中文手册)
  6. 一阶广义差分模型_实验五 自相关性 -
  7. 微信公众号图片上传和预览功能前端实现
  8. android camera预览翻转,android camera yuv帧水平翻转实例
  9. 目前国内的跨境收款通道有哪些还不错的?
  10. 寻中华文化之根 承抗战先烈之志
  11. java蓝牙程序怎么调试_蓝牙BLE调试助手软件源码
  12. 怎样一键比较2个CAD图纸文件的不同呢?
  13. 无纸化车间是怎样实现的,能给企业生产带来什么?
  14. 关闭word后自动打开新的文档
  15. “燕云十六将”之毛毛杜倩(7)
  16. 人脸性别识别文献阅读笔记(3)
  17. 重拾编程之路--jeetcode(java)--Range Sum Query - Immutable
  18. vant 2 Calendar控件IOS下空白
  19. 软件着作权转让交税如何缴纳
  20. java单数字随机抽奖特效_jquery输入数字随机抽奖特效的简单实现代码

热门文章

  1. 4.(地图数据篇)nginx代理地图服务--离线部署地图服务
  2. 一级标题段前段后一行设置方法
  3. visual studio 2019 无法启动程序 系统找不到指定文件
  4. 计算机输入法无法输入小写字母,键盘不能输入小写字母
  5. 关于idea单元测试键盘无法输入的解决方法(终极版)
  6. 上海车牌拍卖突破7.5万元
  7. Android进程管理详解
  8. TCP 建立连接 和 连接释放(Establish)
  9. Could not establish connection to...
  10. java练习题,个人所得税计算