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