javascript
Spring ClassPathResource详解
????????org.springframework.core.io.ClassPathResource位于Spring核心core下,用以表達類路徑下的資源。
 ????????首先簡要說明一下什么是classpath,顧名思義,就是存放*.class類文件的路徑,或者說ClassLoader加載類時為找到 *.class文件的路徑。我們以一個WEB項目為例,發(fā)布后的目錄結(jié)構(gòu)大致如下:
????????然后以Tomcat為例,看一下WEB項目類加載時候的目錄,參考 Tomcat Class Loader How-To 中的說明:
WebappX — A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.
????????因此,對于部署在Tomcat上的WEB應(yīng)用來說,/WEB-INF/classes和/WEB-INF/lib目錄就是我們所指的classpath。
????????ClassPathResource是org.springframework.core.io.Resource接口的實現(xiàn)類。可以使用ClassLoader或Class類加載資源。支持轉(zhuǎn)換為java.io.File對象(在Jar文件中的資源除外)。其繼承實現(xiàn)關(guān)系圖如下:
????????ClasspathResource類的屬性變量和構(gòu)造方法如下:
private final String path;@Nullableprivate ClassLoader classLoader;// 通過ClassLoader加載資源文件@Nullableprivate Class<?> clazz; // 通過Class類加載資源文件// 通過類路徑創(chuàng)建resourcepublic ClassPathResource(String path){...}// 通過類路徑和給定的ClassLoader創(chuàng)建resourcepublic ClassPathResource(String path, @Nullable ClassLoader classLoader){...}// 通過類路徑和給定的Class類創(chuàng)建resourcepublic ClassPathResource(String path, @Nullable Class<?> clazz){...}// 通過類路徑和給定的ClassLoader或Class創(chuàng)建resourceprotected ClassPathResource(String path, @Nullable ClassLoader classLoader, @Nullable Class<?> clazz){...}????????在類繼承關(guān)系中,每個類定義的方法如下:
| 對底層資源的抽象描述 比如文件或類路徑資源 | 對資源接口描述的基礎(chǔ)實現(xiàn) 預(yù)先實現(xiàn)特定的行為 | 將URL解析為文件資源引用的抽象基類,尤其對JBOOS的vfs文件協(xié)議的支持 | 類路徑資源的Resource實現(xiàn) | 
| boolean exists() 判斷該資源是否存在 | public boolean exists() 實現(xiàn)父接口方法,檢查資源(文件或目錄)File對象或資源(文件)InputStream對象是否打開 | public boolean exists() 重寫父類方法,getURL后如果URL的文件協(xié)議是file:、vfsfile:、vfs則返回getFile().exists()直接判斷該文件是否存在,如果非上述文件協(xié)議則嘗試判斷是否網(wǎng)絡(luò)資源,通過HTTP請求看是否返回HTTP Status-Code=200,如果扔非上述,則嘗試getInputStream().close()看文件流是否可打開 | public boolean exists() 重寫父類方法,判斷是否能獲取到該資源的URL對象 | 
| boolean isReadable() 是否可通過InputStreamSource.getInputStream()讀取,這里注意返回true仍然可能讀取失敗,但返回false一定是不能讀取 默認返回exists() | public boolean isReadable() 實現(xiàn)父接口方法,該方法在當(dāng)資源存在的情況下始終返回true,返回值與父接口方法中定義的默認返回值一致,即返回exists() | public boolean isReadable() 重寫父類方法,getURL后如果URL的文件協(xié)議是file:、vfsfile:、vfs則getFile得到該資源File對象,判斷該File資源是否非目錄且canRead可讀,如果非上述文件協(xié)議則嘗試調(diào)用網(wǎng)絡(luò)資源,判斷是否可成功調(diào)用且返回內(nèi)容長度大于0,如果扔非上述,則嘗試getInputStream().close()看文件流是否可打開 | |
| boolean isOpen() 表明該資源是否有打開的stream流,如果返回true則InputStream無法多次讀取,且讀完之后關(guān)閉流以防止內(nèi)存泄露 默認返回false | public boolean isOpen() 實現(xiàn)父接口方法,與接口方法中定義的默認返回值一致,即始終返回false | ||
| boolean isFile() 判斷該文件是否是系統(tǒng)文件中的文件,true值表示(但不保證)可以成功調(diào)用getFile()方法 默認返回false | public boolean isFile() 實現(xiàn)父接口方法,與接口方法中定義的默認返回值一致,即始終返回false | public boolean isFile() 重寫父類方法,getURL后如果url為vfs開頭協(xié)議(vfs/vfsfile)則交給VfsResourceDelegate類判斷,如果url為file協(xié)議則返回true | |
| protected boolean isFile(URI uri) 重載isFile方法,根據(jù)指定的URI判斷該資源是否是一個文件引用,如果URI的scheme以vfs開頭則交給VfsResourceDelegate類判斷,否則判斷如果URI的scheme等于file則返回true | |||
| URL getURL() 返回該資源對應(yīng)的URL | public URL getURL() 實現(xiàn)父接口方法,這里假設(shè)資源不能解析為URL,直接返回了FileNotFoundException異常 | public URL getURL() 重寫父類方法,根據(jù)類路徑參數(shù)獲取該資源的URL對象 | |
| URI getURI() 返回該資源對應(yīng)的URI | public URI getURI() 實現(xiàn)父接口方法,基于getURL返回的URL構(gòu)建一個URI | ||
| File getFile() 返回該資源的File對象 | public File getFile() 實現(xiàn)父接口方法,這里假設(shè)資源無法解析為文件絕對路徑,直接返回了FileNotFoundException異常 | public File getFile() 重寫父類方法,父類直接返回FileNotFoundException異常,在這里通過getURL獲取到URL對象(具體URL由其子類確定,比如ClasspathResource重寫了getURL通過類加載器獲取到了類路徑資源的URL),如果url為vfs開頭協(xié)議(vfs/vfsfile)則交給VfsResourceDelegate類獲取File對象,否則通過得到url獲取File對象 | |
| protected File getFile(URI uri) 重載getFile方法,根據(jù)指定的URI獲取資源File對象,如果URI的scheme以vfs開頭則交給VfsResourceDelegate類獲取 | |||
| ReadableByteChannel readableChannel() 默認返回Channels.newChannel(getInputStream()) | public ReadableByteChannel readableChannel() 實現(xiàn)父接口方法,與父接口的默認返回值相同 | public ReadableByteChannel readableChannel() 根據(jù)指定的URI調(diào)用FileChannel.open 返回一個ReadableByteChannel對象 | |
| long contentLength() 返回該資源內(nèi)容的長度 | public long contentLength() 根據(jù)getInputStream()返回的InputStream,讀取并計算資源的內(nèi)容長度 | public long contentLength() 根據(jù)getURL獲得URL對象,如果是文件(file/vfsfile/vfs)URL返回文件長度,否則嘗試網(wǎng)絡(luò)連接獲取資源并返回長度 | |
| long lastModified() 返回該資源最后一次修改的時間戳 | public long lastModified() 獲取并返回該資源文件的時間戳 | public long lastModified() 根據(jù)getURL獲取URL對象,如果是文件(file/vfsfile/vfs)或歸檔文件(jar/war/zip/vfszip/wsjar)則獲取文件的最后修改時間戳,否則獲取網(wǎng)絡(luò)連接并獲取最后修改時間戳 | |
| Resource createRelative(String relativePath) 根據(jù)相對于該資源的相對路徑,創(chuàng)建一個Resource資源,比如classpath資源目錄conf下有A.xml和B.xml,Resource a = new ClassPathResource("conf/A.xml"); 那么在創(chuàng)建b資源的時候就可以以a為參照Resource b = a.createRelative("B.xml"); | public Resource createRelative(String relativePath) 實現(xiàn)父接口方法,這里假設(shè)改相對資源未被創(chuàng)建,直接返回了FileNotFoundException異常 | public Resource createRelative(String relativePath) 重寫父類方法,根據(jù)參照資源的類路徑得到relativePath參數(shù)的真實classpath路徑,并創(chuàng)建Resource資源對象 | |
| String getFilename() 返回該資源的文件名,通常是路徑的最后一部分,比如:myfile.txt | public String getFilename() 實現(xiàn)父接口方法,這里假設(shè)該資源無文件名,直接返回了null | public String getFilename() 重寫父類方法,根據(jù)classpath截取后面的文件名并返回 | |
| String getDescription() 返回該資源的描述,用于該資源在處理時的錯誤輸出 | public String getDescription() 重寫父類方法,返回格式如class path resource [...]的內(nèi)容 | ||
| protected File getFileForLastModifiedCheck() 獲取用于時間戳檢查的文件,這里默認返回了getFile() | protected File getFileForLastModifiedCheck() 重寫父類方法,擴展了父類方法,在getFile之前先判斷url協(xié)議是否為jar/war/zip/vfszip/wsjar,如果是則獲取最外層的文件URL對應(yīng)的File對象,比如嵌套在war中的jar文件,則返回war文件File對象。這里判斷vfs開頭協(xié)議扔交給VfsResourceDelegate類來處理 | ||
| public boolean equals(Object other) 重寫Object的equals方法,用于比較兩個Resource的Description是否相同 | public boolean equals(Object other) 重寫Object方法,比較類路徑的值是否相同 | ||
| public int hashCode() 重寫Object的hashCode方法,用于獲取Resource的Description值的hashCode值 | public int hashCode() 重寫Object方法,獲取類路徑classpath的hashCode值 | ||
| public String toString() 重寫Object的toString方法,返回Resource的Description信息 | |||
| public final String getPath() 返回該資源的classpath,構(gòu)造函數(shù)的path參數(shù)經(jīng)過規(guī)范化處理的結(jié)果 | |||
| public final ClassLoader getClassLoader() 如果指定了Class,則通過該Class獲取ClassLoader,否則返回屬性變量的ClassLoader參數(shù) | |||
| public InputStream getInputStream() Resource繼承了InputStreamSource接口,在ClassPathResource中得到了具體的實現(xiàn),根據(jù)資源路徑得到文件流 | 
????????在AbstractFileResolvingResource類中由于增加了對JBOOS的vfs文件協(xié)議的支持,因此包含了一個`VfsResourceDelegate`內(nèi)部類用于獲取`VfsResource`類型資源對象,該資源對象同樣繼承自`AbstractResource`抽象類,并針對vfs文件的特點對方法進行了重寫。如下: /*** Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.*/ private static class VfsResourceDelegate {public static Resource getResource(URL url) throws IOException {return new VfsResource(VfsUtils.getRoot(url));}public static Resource getResource(URI uri) throws IOException {return new VfsResource(VfsUtils.getRoot(uri));} }
ClassPathResource的使用:
Resource resource = new ClassPathResource("conf/custom-beans.xml");參數(shù)path應(yīng)在類路徑下能夠被ClassLoader所加載。
????????獲取到了Resource對象也就等于獲取到了該資源文件,后面可以根據(jù)方法的定義對文件進行相關(guān)操作。
System.out.println(resource.getURL()); System.out.println(resource.getFilename()); System.out.println(resource.getFile().getPath()); // ... ....總結(jié)
以上是生活随笔為你收集整理的Spring ClassPathResource详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: My Sixth-First - 解数独
- 下一篇: 【opencv14】cv::Mat---
