一起学SF框架系列6.1-spring-core-Resource

Spring的Resource接口提供了一种更丰富的资源访问方式,超越了Java的URL类。它支持从类路径、文件系统、URL等多种位置获取资源,并有检查资源是否存在、获取输入流等方法。ResourceLoader和ResourcePatternResolver接口进一步扩展了资源加载和路径通配符处理的功能,使得在不同场景下加载资源更为灵活。
摘要由CSDN通过智能技术生成

  Java虽然提供了java.net.URL类和各种URL前缀处理程序来负责处理对各种资源的访问,但对于低级别资源的访问来说还是不够充分。例如,没有标准化的实现可用于访问需要从类路径中获取或者相对于一个ServletContext的资源;也没有检查所指向的资源是否存在的标准方法。因此Spring提供了Resource来达成目的。

类作用

  Resource是Spring的资源抽象,本质上是JDKjava.net.URL类的一个功能更丰富的版本。Resource可以以透明的方式从几乎任何位置获得低级资源,包括从类路径、文件系统位置、可以用标准URL描述的任何位置以及其他一些变体。如果资源位置字符串是一个没有任何特殊前缀的简单路径,那么这些资源的来源是特定的,并且适合于实际的应用程序容器类型。
  Spring本身广泛使用Resource,其实应用容器(ApplicationContext)本身就是个ResourceLoader,可用于加载Resource对象。提供给ApplicationContext构造函数的一个或多个位置路径实际上是资源字符串,并且以简单的形式根据特定的容器实现进行适当处理。例如,ClassPathXmlApplicationContext将简单的位置路径视为类路径位置。您还可以使用带有特殊前缀的位置路径(资源字符串)来强制从类路径或URL加载定义,而不考虑实际的容器类型。
  虽然Spring本身使用Resource接口很多,但它实际上是一个非常方便的通用实用程序类,用于在自己的代码中访问资源,即使你的代码不知道或关心Spring的任何其他部分。虽然这会使你的代码与Spring耦合,但它只会将其与这个小集合的实用程序类耦合,这些实用程序类可以作为URL的更强大的替代品,并且可以被认为是用于此目的的任何其他库的等效物。
Resource主要关注安全可靠的读取资源,其方法如下:

public interface Resource extends InputStreamSource {
	//资源是否以物理形式存在
	boolean exists();
	
	boolean isReadable();
	//资源是否已打开
	boolean isOpen();

	boolean isFile();

	URL getURL() throws IOException;

	URI getURI() throws IOException;

	File getFile() throws IOException;

	ReadableByteChannel readableChannel() throws IOException;

	long contentLength() throws IOException;

	long lastModified() throws IOException;

	Resource createRelative(String relativePath) throws IOException;

	String getFilename();
	//返回资源描述,通常是文件全路径名或完整的URL
	String getDescription();
}
//父接口
public interface InputStreamSource {
	//定位并打开资源,返回输入流
	InputStream getInputStream() throws IOException;
}

实际上,Resource本身作为一个通用工具类,在我们的应用代码中可直接使用,可以非常方便访问资源。
注:由于Resource主要就是用于访问资源,因此只有读取相关的方法,没有修改/写入的方法。针对有修改需求的资源,通过子类接口WritableResource提供。

类关系图

基于Resource的目的,spring构建按了整个Resource实现的体系,其类关系图如下:
在这里插入图片描述

1、Resouce继承了InputStreamSource,通过来源getInputStream()统一转换为输入流InputStream,以便访问。
2、AbstractResource是Resource的基础实现,除了getInputStream由子类实现外,其它资源的访问等典型行为均统一实现了。
3、AbstractResource的子孙类就是各种具体资源的实现,包括:
AbstractFileResolvingResource:实现对URL/URI类资源访问
  UrlResource:实现java.net.URL定位的资源访问,支持"file:"协议
    FileUrlResource:是在UrlResource基础上增加修改资源能力
  ClassPathResource:实现通过classpath寻址的资源访问
FileSystemResource:实现java.io.File或java.nio.file.Path定位的资源访问
ByteArrayResource:实现来自ByteArray的资源访问
InputStreamResource:实现来自InputStream的资源访问
PathResource:实现java.nio.file.Path定位的资源访问
VfsResource:实现基于JBoss VFS定位的资源访问
4、WritableResource是增加Resource可写入能力,支持的类包括:FileUrlResource、FileSystemResource、PathResource。

类实现

UrlResource

UrlResource针对来自java.net.URL类资源的对象,如文件、HTTPS目标、FTP目标等。所有URL都是一个标准化的字符串,一般通过标准化前缀来指示URL类型。标准化前缀包括:"file:"表示通过文件系统路径访问资源;“https:"或“http:"表示通过https/http协议访问资源;”ftp:“表示通过ftp协议访问资源等。

ClassPathResource

ClassPathResource类表示从类路径(ClassPath)获得的资源。

FileSystemResource

FileSystemResource是针对访问java.io.File句柄或java.nio.file.Path句柄资源的Resource实现。
java.nio.path.path句柄资源的访问见PathResource。
FileSystemResource的资源路径总是相对于应用根目录,无论第一个字符是否有”/",如下面两个语句是等效的:

ApplicationContext ctx =
	new FileSystemXmlApplicationContext("conf/context.xml");

ApplicationContext ctx =
	new FileSystemXmlApplicationContext("/conf/context.xml");

PathResource

PathResource是针对访问java.nio.file.Path句柄的Resource实现,通过Path API执行所有操作和转换。它支持解析为文件和URL,还实现了扩展的WritableResource接口。
PathResource实际上是FileSystemResource的纯java.nio.path.path替代方案。

ServletContextResource

ServletContextResource是针对访问ServletContext资源的Resource实现,用于相关web应用程序根目录中的相对路径。

InputStreamResource

InputStreamResource是针对访问已打开的InputStream的Resource实现。

ByteArrayResource

ByteArrayResource是把一个给定字节数组当作资源访问的Resource实现。它为给定的字节数组创建一个ByteArrayInputStream。

资源加载

资源加载器

Resource只管负责资源访问,资源如何加载进来就要靠加载类完成。
资源加载器是个统一接口:

public interface ResourceLoader {

	Resource getResource(String location);

	ClassLoader getClassLoader();
}

ResourceLoader实现类关系图如下:
在这里插入图片描述
ResourceLoader:通用加载资源接口。
DefaultResourceLoader:通用资源加载实现(阅读下getResource(String location)实现)。有特殊加载方式通过子类实现,包括:ClassRelativeResourceLoader、FileSystemResourceLoader。
所有类型的应用容器都实现了ResourceLoader。

ResourcePatternResolver-路径通配符处理

ResourcePatternResolver接口是ResourceLoader接口的扩展,该接口定义了把包含"classpath*:"或Ant正则表达式通配符的资源位置下的所有资源解析为Resource对象。
1、"classpath*:"表示类路径下所有目录或jar包中,与给定名称匹配的类路径资源都进行加载。
2、Ant正则表达式通配符有三种:
  ? :匹配任何单字符
  * :匹配0或者任意数量的字符
  **:匹配0或者更多的目录
ResourcePatternResolver接口如下:

public interface ResourcePatternResolver extends ResourceLoader {

	String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

	Resource[] getResources(String locationPattern) throws IOException;
}

PathMatchingResourcePatternResolver是接口ResourcePatternSolver的独立实现,可脱离容器之外使用。
任何标准ApplicationContext中的默认ResourceLoader实际上都是PathMatchingResourcePatternResolver的一个实例。

应用访问资源

直接获取使用

引用程序可利用Resource获得使用资源的能力。举例代码如下:

/*依据ctx的容器类型加载资源,并返回适当的Resource对象
ClassPathXmlApplicationContext:返回ClassPathResource
FileSystemXmlApplicationContext:返回FileSystemResource
WebApplicationContext:返回ServletContextResource
*/
Resource res= ctx.getResource("some/resource/path/myTemplate.txt");

//在classpath下查找资源并加载 
Resource res= ctx.getResource("classpath:some/resource/path/myTemplate.txt");

//以URL方式(file协议)加载资源
Resource res= ctx.getResource("file:///some/resource/path/myTemplate.txt");

//以URL方式(https协议)加载资源
Resource res= ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");

Aware方式获取

要使用资源的应用类实现ResourceLoaderAware接口,应用启动过程中,SF会自动把ResourceLoader接入到到应用类。代码如下:

public interface ResourceLoaderAware {
	void setResourceLoader(ResourceLoader resourceLoader);
}

//应用
public class TestResource implements ResourceLoaderAware {
	private ResourceLoader  resourceLoader ;
	void setResourceLoader(ResourceLoader resourceLoader){
		this.resourceLoader  = resourceLoader ;
	}
	...
}

应用类也可以实现ApplicationContextAware,因为ApplicationContext就是本身的祖先类就是ResourceLoader。

静态资源bean

如果bean本身将通过某种动态过程来确定和提供资源。如果bean是动态资源(如考虑加载某种类型的模板,其中所需的特定资源取决于用户的角色),可使用ResourceLoader或ResourcePatternResolver接口加载资源。如果资源是静态的,可完全消除对ResourceLoader接口(或ResourcePatternResolver接口)的使用,可通过bean配置直接注入,而且可多种方式。举例如下:
注入方式1:

public class MyBean {

	private Resource resource;

	public setResource(Resource resource) {
		this.resource= resource;
	}

	// ...
}

配置如下:

<bean id="myBean" class="example.MyBean">
	<property name="resource" value="some/resource/path/myResource.txt"/>
</bean>

注入方式2:

@Component
public class MyBean {

	private final Resource[] resources;
	//resources.path是在应用属性文件中配置的
	public MyBean(@Value("${resources.path}") Resource[] resources) {
		this.resources= resources;
	}
	// ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐享技术

每一个打赏,都是对我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值