spring核心技术之Resource资源理解
文章目錄
- 1 介紹
- 2 Resource 接口
- resource接口提供哪些功能?
- 3 spring為我們提供了哪些內置的Resource實現
- 3.1 URLResource
- 3.2 ClassPathResource
- 3.3 FileSystemResource
- 3.4 InputStreamResource
- 3.5 ByteArrayResource
- 4 ResourceLoader 資源加載
- 5 ResourceLoaderAware
- 6 Resources as Dependencies
- 7 Application Contexts and Resource Paths
- 7.1 Constructing Application Contexts
- 7.2Wildcards in Application Context Constructor Resource Paths
- **Ant-style Patterns**
- 可移植性
- The `classpath*:` Prefix
- FileSystemResource Caveats
spring如何處理資源(Resource),我們如何在spring中和資源(Resource)工作呢?
1 介紹
java.net.URL
可以處理各種復雜的URL(統一資源定位),缺點是對于所有訪問底層資源的能力還不夠
例如還沒有一種URL的實現可以訪問需要從類路徑或相對于ServletContext獲得的資源雖然可以為專門的URL前綴注冊新的處理程序(類似于現有的用于前綴的處理程序,如http:),但這通常非常復雜。而且URL接口仍然缺少一些需要的功能,比如檢查被指向的資源是否存在的方法
思考:Resource接口是用來解決什么問題的?即URL接口的這些不足。
2 Resource 接口
比URL接口更強,用于抽象對底層資源的訪問。
對比URL接口,Resource接口有何不同,URL表示一個統一的資源定位符,一個指向萬維網上“資源”的指針,相較于Resource更加側重于web資源,且無法判斷資源是否存在
相較于URL Resource接口實現資源的抽象,可以檢查資源是否存在。
URL protocol,host,port,authority,file,ref
resource接口提供哪些功能?
| isReadable | URL | createRelative |
| isOpen | URI | contentLength |
| isFile | File | lastModified |
| exists | InputStream | ReadableByteChannel |
通過字符串路徑上的特殊前綴,指定必須創建和使用特定的資源實現,例如:ftp,http,file
資源抽象不能代替功能。在可能的地方進行包裝。例如,UrlResource包裝一個URL并使用包裝后的URL來完成它的工作。
Resource接口的子類有以下這些
3 spring為我們提供了哪些內置的Resource實現
- UrlResource
- ClassPathResource
- FileSystemResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
3.1 URLResource
包裝了URL接口,可以用來訪問File,Http,ftp等其他對象,UrlResource是由Java代碼顯式地使用UrlResource構造函數創建的,但通常在調用API方法時隱式地創建,該方法接受一個表示路徑的字符串參數。對于后一種情況,JavaBeans PropertyEditor最終決定創建哪種類型的資源。路徑字符串包含眾所周知的(也就是)前綴(例如classpath:),它為該前綴創建一個適當的專門化資源。但是,如果它不識別前綴,則假定該字符串是標準URL字符串,并創建一個UrlResource。
PropertyEditor
3.2 ClassPathResource
從類路徑下獲取(classpath),隱式創建當字符串路徑上的特殊前綴classpath:,PropertyEditor將創建一個ClassPathResource實例
3.3 FileSystemResource
File和Path 的Resource實現,支持解析File和URL
3.4 InputStreamResource
InputStream的Resource實現,只有在沒有特定的資源實現可用時,才應該使用它。特別是,盡可能選擇ByteArrayResource或任何基于文件的資源實現。如果您需要將資源描述符保存在某個地方,或者需要多次讀取流,請不要使用它
3.5 ByteArrayResource
這是一個給定字節數組的資源實現。它為給定的字節數組創建一個ByteArrayInputStream。它對于從任何給定的字節數組加載內容都很有用,而不必求助于一次性使用的InputStreamResource
| File,Path | FileSystemResource |
| InputStreamResource | 盡量不用 |
| ByteArrayResource | byte array --ByteArrayInputStream |
4 ResourceLoader 資源加載
由可以返回(即加載)資源實例的對象來實現的。
public interface ResourceLoader {Resource getResource(String location); }applicationcontext于resouce的關系,如果沒有指定特殊前綴,將獲得適合于特定應用程序上下文的資源類型
| ClassPathXmlApplicationContext | ClassPathResource |
| FileSystemXmlApplicationContext | FileSystemResource |
| WebApplicationContext | ServletContextResource |
用例
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt"); Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");資源和字符串路徑的關系
| 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. |
5 ResourceLoaderAware
當類實現ResourceLoaderAware并部署到應用程序上下文中(作為Spring托管的bean)時,該類被應用程序上下文識別為ResourceLoaderAware。 然后,應用程序上下文調用setResourceLoader(ResourceLoader),將自身作為參數提供(請記住,Spring中的所有應用程序上下文均實現ResourceLoader接口)
在應用程序組件中,您還可以依賴自動裝配ResourceLoader來實現ResourceLoaderAware接口。 “傳統”構造函數和byType自動裝配模式(如“自動裝配協作器”中所述)能夠分別為構造函數參數或setter方法參數提供ResourceLoader。 為了獲得更大的靈活性(包括自動裝配字段和多個參數方法的能力),請考慮使用基于注釋的自動裝配功能。 在這種情況下,只要有問題的字段,構造函數或方法帶有@Autowired批注,ResourceLoader就會自動連接到需要ResourceLoader類型的字段,構造函數參數或方法參數中。 有關更多信息,請參見使用@Autowired。
即ResourceLoaderAware 接口可以獲得實現了ResourceLoader的類,好像還與自動裝配存在著某種聯系。自動裝配的核心是BeanpostProcessor,其可以在bean實例化前后對bean進行一系列操作。
6 Resources as Dependencies
資源可以作為依賴
<bean id="myBean" class="..."><property name="template" value="some/resource/path/myTemplate.txt"/><property name="template" value="file:///some/resource/path/myTemplate.txt"/><property name="template" value="classpath:some/resource/path/myTemplate.txt"> </bean>7 Application Contexts and Resource Paths
應用上下文和資源路徑
7.1 Constructing Application Contexts
創建應用上下文需要依賴資源路徑,應用上下文從資源路徑中加載bean的定義,當這樣的位置路徑沒有前綴時,從該路徑構建并用于加載bean定義的特定資源類型依賴于特定的應用程序上下文,并且適合于特定的應用程序上下文。
| new ClassPathXmlApplicationContext(“conf/appContext.xml”); | classpath |
| new FileSystemXmlApplicationContext(“conf/appContext.xml”); | file system |
| new FileSystemXmlApplicationContext(“classpath:conf/appContext.xml”); | classpath |
使用FileSystemXmlApplicationContext從類路徑加載bean定義。但是,它仍然是FileSystemXmlApplicationContext。如果它隨后被用作ResourceLoader,那么任何不帶前綴的路徑仍然被視為文件系統路徑。
com/foo/services.xmldaos.xmlMessengerService.class以下示例顯示如何實例化由在名為service.xml和daos.xml(位于類路徑中)的文件中定義的bean組成的ClassPathXmlApplicationContext實例。
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}, MessengerService.class);感覺對于classpath 和包名之間的關系還是有點不清晰
7.2Wildcards in Application Context Constructor Resource Paths
應用程序上下文構造器資源路徑中的通配符
此機制的一個用途是,當您需要進行組件樣式的應用程序組裝時。所有組件都可以將上下文定義片段“發布”到一個已知的位置路徑,并且,當使用以classpath*:作為前綴的相同路徑創建最終的應用程序上下文時,所有組件片段都會自動被獲取。注意,這種通配符是特定于在應用程序上下文構造函數中使用資源路徑的,在構建應用時進行解析。
與資源類型本身無關。您不能使用classpath*:前綴來構造實際的資源,因為一個資源一次只能指向一個資源。
多模塊應用中的使用classpath*
Ant-style Patterns
/WEB-INF/*-context.xml com/mycompany/**/applicationContext.xml file:C:/some/path/*-context.xml classpath:com/mycompany/**/applicationContext.xmlWhen the path location contains an Ant-style pattern, the resolver follows a more complex procedure to try to resolve the wildcard. It produces a Resource for the path up to the last non-wildcard segment and obtains a URL from it. If this URL is not a jar: URL or container-specific variant (such as zip: in WebLogic, wsjar in WebSphere, and so on), a java.io.File is obtained from it and used to resolve the wildcard by traversing the filesystem. In the case of a jar URL, the resolver either gets a java.net.JarURLConnection from it or manually parses the jar URL and then traverses the contents of the jar file to resolve the wildcards.
如果有路徑機制含有 Ant-style pattern,解析器會使用更加復雜的程序嘗試解析通配符。
匹配規則
The mapping matches URLs using the following rules:
- ? matches one character
- ***** matches zero or more characters
- ** matches zero or more ‘directories’ in a path
- {spring:[a-z]+} matches the regexp [a-z]+ as a path variable named “spring”
Some examples:
- com/t?st.jsp - matches com/test.jsp but also com/tast.jsp or com/txst.jsp
- com/*.jsp - matches all .jsp files in the com directory
- com/**/test.jsp - matches all test.jsp files underneath the com path
- org/springframework/**/*.jsp - matches all .jsp files underneath the org/springframework path
- org/**/servlet/bla.jsp - matches org/springframework/servlet/bla.jsp but also org/springframework/testing/servlet/bla.jsp and org/servlet/bla.jsp
- com/{filename:\w+}.jsp will match com/test.jsp and assign the value test to the filename variable
可移植性
如果指定的路徑已經是一個文件URL(由于基本ResourceLoader是一個文件系統,所以它是隱式的,或者是顯式的),則保證通配符可以完全可移植的方式工作。
如果指定的路徑是類路徑位置,則解析器必須通過調用Classloader.getResource()獲得最后的非通配符路徑段URL。 由于這只是路徑的一個節點(而不是末尾的文件),因此實際上(在ClassLoader javadoc中)未定義確切返回的是哪種URL。 實際上,它始終是一個java.io.File,代表目錄(類路徑資源解析為文件系統位置)或某個jar URL(類路徑資源解析為jar位置)。 盡管如此,此操作仍存在可移植性問題。
如果為最后一個非通配符段獲取了jar URL,則解析程序必須能夠從中獲取java.net.JarURLConnection或手動解析jar URL,以便能夠遍歷jar的內容并解析通配符 。 這在大多數環境中確實有效,但在其他環境中則無效,因此我們強烈建議您在依賴特定環境之前,對來自jars的資源的通配符解析進行徹底測試
移植性于路徑關系
| file URL | 無影響 |
| classpath location | 可能有一些 |
| jar URL | 徹底測試 |
The classpath*: Prefix
在構造基于xml的應用程序上下文時,位置字符串可以使用特殊的classpath*:前綴,如下面的示例所示
ApplicationContext ctx =new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");這個特殊的前綴指定必須獲取所有與給定名稱匹配的類路徑資源(在內部,這實際上是通過調用ClassLoader來實現的。然后合并形成最終的應用程序上下文定義
通配符類路徑依賴于基礎類加載器的getResources()方法。 由于當今大多數應用程序服務器都提供自己的類加載器實現,因此行為可能有所不同,尤其是在處理jar文件時。 檢查classpath *是否可行的簡單測試是使用classloader從classpath的jar中加載文件:getClass()。getClassLoader()。getResources(“ ”)。 嘗試對具有相同名稱但位于兩個不同位置的文件進行此測試。 如果返回了不合適的結果,請檢查應用程序服務器文檔中可能影響類加載器行為的設置。
還可以在其余位置路徑中將classpath *:前綴與PathMatcher模式結合使用(例如,classpath *:META-INF / *-beans.xml)。 在這種情況下,解析策略非常簡單:在最后一個非通配符路徑段上使用ClassLoader.getResources()調用,以獲取類加載器層次結構中的所有匹配資源,然后從每個資源獲取相同的PathMatcher解析 前面描述的策略用于通配符子路徑。
注意classpath*:,當與 Ant-style模式結合使用時,除非實際的目標文件駐留在文件系統中,否則classpath*:只能在模式啟動之前可靠地與至少一個根目錄一起工作。這意味著,類似classpath*😗.xml這樣的模式可能不會從jar文件的根目錄檢索文件,而是只從擴展目錄的根目錄檢索文件。
帶有類路徑的ant樣式模式:如果要搜索的根包在多個類路徑位置可用,則不能保證資源能夠找到匹配的資源。考慮下面的資源位置示例
com/mycompany/package1/service-context.xml現在考慮某人可能用來嘗試找到該文件的Ant樣式路徑
classpath:com/mycompany/**/service-context.xml這樣的資源可能只在一個位置,但是當使用諸如上一示例的路徑嘗試對其進行解析時,解析器將根據getResource(“ com / mycompany”)返回的(第一個)URL進行工作。如果此基本包節點存在于多個類加載器位置,則實際的最終資源可能不存在。因此,在這種情況下,您應該使用與ant樣式相同的classpath*:,它搜索包含根包的所有類路徑位置。
FileSystemResource Caveats
文件系統資源警告
未附加到FileSystemApplicationContext的FileSystemResource(即,當FileSystemApplicationContext不是實際的ResourceLoader時)將按您期望的那樣處理絕對路徑和相對路徑。 相對路徑是相對于當前工作目錄的,而絕對路徑是相對于文件系統的根的。
但是,出于向后兼容性(歷史原因)的原因,當FileSystemApplicationContext是ResourceLoader時,這種情況會發生變化。FileSystemApplicationContext強制所有附加的FileSystemResource實例將所有位置路徑視為相對路徑,不管它們是否以正斜杠開頭。在實踐中,這意味著下面的例子是等價的
ApplicationContext ctx = **new** FileSystemXmlApplicationContext("conf/context.xml"); ApplicationContext ctx =new FileSystemXmlApplicationContext("/conf/context.xml");下面的例子也是等價的(盡管它們不同是有意義的,因為一種情況是相對的,另一種情況是絕對的)
FileSystemXmlApplicationContext ctx = ...; ctx.getResource("some/resource/path/myTemplate.txt"); FileSystemXmlApplicationContext ctx = ...; ctx.getResource("/some/resource/path/myTemplate.txt");在實踐中,如果您需要真正的絕對文件系統路徑,您應該避免將絕對路徑與FileSystemResource或FileSystemXmlApplicationContext一起使用,并通過使用file: URL前綴強制使用UrlResource。下面的例子演示了如何做到這一點
// actual context type doesn't matter, the Resource will always be UrlResource ctx.getResource("file:///some/resource/path/myTemplate.txt"); ApplicationContext ctx =new FileSystemXmlApplicationContext("file:///conf/context.xml");參考文檔
總結
以上是生活随笔為你收集整理的spring核心技术之Resource资源理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 小说系统_java 实现小说管
- 下一篇: T410安装3G模块