Spring Core Resource 随手笔记

Resource Interface

Spring的Resource接口旨在成为一种功能更强大的接口,用于抽象化对低级资源的访问。以下清单显示了Resource接口定义:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JsVXXJfz-1587895443891)(leanote://file/getImage?fileId=5ea54f07fba2f45278000004)]

重要方法:

  • getInputStream():打开资源,返回一个InputStream以便从资源中读取。每次调用都会返回一个新的InputStream。调用者需要手动关闭流。
  • exist():返回一个布尔值,指示此资源是否存在。
  • isOpen():返回一个布尔值,指示此资源是否已打开。如果为true,则不能多次读取InputStream,必须只读取一次,然后将其关闭以避免资源泄漏。对于所有常规资源实现,返回false,但InputStreamResource除外。
  • getDescription():返回对此资源的描述,用于在处理资源时用于错误输出。这通常是标准文件名或资源的实际URL。

主要子类

UrlResource

UrlResource包装了java.net.URL,可用于访问通常可以通过URL访问的任何对象,例如文件,HTTP目标,FTP目标等。所有URL都具有标准化的String表示形式,因此,使用适当的标准化前缀来指示另一种URL类型。这包括file:用于访问文件系统路径,http:通过HTTP协议访问资源,ftp:通过FTP访问资源等。
UrlResource是由Java代码通过显式使用UrlResource构造函数创建的,但通常在调用带有String参数表示路径的API方法时隐式创建。对于后一种情况,JavaBeans PropertyEditor最终决定要创建哪种类型的资源。如果路径字符串包含众所周知的前缀(例如,classpath :),则会为该前缀创建适当的专用资源。但是,如果它不能识别前缀,则假定该字符串是标准URL字符串并创建一个UrlResource。

ClassPathResource

此类表示应从类路径获取的资源。它使用线程上下文类加载器,给定的类加载器或给定的类来加载资源。

如果类路径资源驻留在文件系统中,而不是驻留在jar中并且尚未(通过servlet引擎或任何环境将其扩展到)文件系统的类路径资源驻留在文件系统中,则此Resource实现以java.io.File支持解析。为了解决这个问题,各种Resource实现始终支持将解析作为java.net.URL。
Java代码通过显式使用ClassPathResource构造函数来创建ClassPathResource,但通常在调用带有String参数表示路径的API方法时隐式创建ClassPathResource。对于后一种情况,JavaBeans PropertyEditor会识别字符串路径上的特殊前缀classpath:,并在这种情况下创建ClassPathResource。

FileSystemResource

这是java.io.File和java.nio.file.Path句柄的Resource实现。它支持解析为文件和URL。

ServletContextResource

这是ServletContext资源的Resource实现,用于解释相关Web应用程序根目录中的相对路径。它始终支持流访问和URL访问,但仅在扩展Web应用程序档案且资源实际位于文件系统上时才允许java.io.File访问。它是在文件系统上扩展还是直接扩展,或者是否可以直接从JAR或其他类似数据库(可以想到的)中访问,实际上取决于Servlet容器。

InputStreamResource

InputStreamResource是给定InputStream的Resource实现。仅当没有特定的资源实现适用时才应使用它。特别是,尽可能选择ByteArrayResource或任何基于文件的Resource实现。
与其他Resource实现相反,这是一个已经打开的资源的描述符。因此,它从isOpen()返回true。如果需要将资源描述符保存在某个地方,或者需要多次读取流,请不要使用它。

ByteArrayResource

这是给定字节数组的Resource实现。它为给定的字节数组创建一个ByteArrayInputStream。
这对于从任何给定的字节数组加载内容很有用,而不必求助于一次性InputStreamResource。

ResourceLoader

ResourceLoader接口旨在由可以返回(即加载)Resource实例的对象实现。以下清单显示了ResourceLoader接口定义:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1S2mZ2RO-1587895443894)(leanote://file/getImage?fileId=5ea554b8fba2f45278000005)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWlJ9T7H-1587895443896)(leanote://file/getImage?fileId=5ea55509fba2f45278000006)]

所有Application Context 都实现ResourceLoader接口。因此,所有应用程序上下文都可用于获取Resource实例。

当您在特定的 Application Context中调用getResource(),并且指定的位置路径没有特定的前缀时,您将获得适合该特定应用程序上下文的Resource类型。

org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResources
org.springframework.core.io.DefaultResourceLoader#getResource
@Override
	public Resource[] getResources(String locationPattern) throws IOException {
		Assert.notNull(locationPattern, "Location pattern must not be null");
		if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
			// a class path resource (multiple resources for same name possible)
			if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
				// a class path resource pattern
				return findPathMatchingResources(locationPattern);
			}
			else {
				// all class path resources with the given name
				return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
			}
		}
		else {
			// Generally only look for a pattern after a prefix here,
			// and on Tomcat only after the "*/" separator for its "war:" protocol.
			int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
					locationPattern.indexOf(':') + 1);
			if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
				// a file pattern
				return findPathMatchingResources(locationPattern);
			}
			else {
				// a single resource with the given name
				return new Resource[] {getResourceLoader().getResource(locationPattern)};
			}
		}
	}

循环全部去查找

@Override
	public Resource getResource(String location) {
		Assert.notNull(location, "Location must not be null");

		for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
			Resource resource = protocolResolver.resolve(location, this);
			if (resource != null) {
				return resource;
			}
		}

		if (location.startsWith("/")) {
			return getResourceByPath(location);
		}
		else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
		}
		else {
			try {
				// Try to parse the location as a URL...
				URL url = new URL(location);
				return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
			}
			catch (MalformedURLException ex) {
				// No URL -> resolve as resource path.
				return getResourceByPath(location);
			}
		}
	}

##下表总结了将String对象转换为Resource对象的策略:

Prefix Example Explanation
classpath: classpath:com/myapp/config.xml Loaded from the classpath.
file: file:///data/config.xml Loaded as a URL from the filesystem. See also FileSystemResource Caveats.
http: https://myserver/logo.png Loaded as a URL.
(none) /data/config.xml Depends on the underlying ApplicationContext.取决于 pplicationContext。 实现

ResourceLoaderAware接口

ResourceLoaderAware接口是一个特殊的回调接口,用于标识期望随ResourceLoader参考一起提供的组件。
Spring 源码调用

org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8kF6UBj4-1587895443899)(leanote://file/getImage?fileId=5ea55b09fba2f45278000007)]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章