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)]

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