Application context 和Resource 路徑

來源:互聯網
上載者:User
4.7. Application context 和Resource 路徑
     Spring提供對資源檔的泛型訪問(Generic access),ApplicationContext繼承了org.springframework.core.io.Resource介面,org.springframework.core.io.Resource介面代表著物理存在的任何資源,其繼承於org.springframework.core.io.InputStreamSource;其子類有如下幾種:ByteArrayResource, ClassPathResource, DescriptiveResource, FileSystemResource, InputStreamResource, PortletContextResource, ServletContextResource, UrlResource 。常用的有以下四種:
  1. ClassPathResource:通過 ClassPathResource 以類路徑的方式進行訪問; 類路(classpath): 顧名思義,即類檔案的輸出路徑。可通過Java Build Path -> Source -> Output folder/Default output folder 查看,如若是java 工程預設是bin ,若是web 工程預設是 classes。
  2. FileSystemResource:通過 FileSystemResource 以檔案系統絕對路徑相對路徑的方式進行訪問;                                  如:(1)絕對路徑:Resource resource = context.getResource("file:c:/workspace/oms/config/applicationContext-ibatis.xml")。                                           (2)相對路徑:但是如果使用相對路徑要注意其根目錄。例如在eclipse中,它的根目錄就是你工程目錄作為你的根目錄。Resource resource = context.getResource("config/applicationContext-ibatis.xml")。                                             ...然後,由於使用的是XML檔案,所以使用org.springframework.beans.factory.xml.XmlBeanFactory類,XmlBeanFactory實現了org.springframework.beans.factory.BeanFactory 介面,用來讀取定義並建立BeanFactory執行個體。                       BeanFactory factory = new XmlBeanFactory(resource);    test aa = (test)factory.getBean("applicationListDao1");                            
  3. ServletContextResource:通過 ServletContextResource 以相對於Web應用根目錄的方式進行訪問。如:Resource resource = context.getResource("WEB-INF/conf/applicationContext-ibatis.xml")。 
  4. UrlResource :通過java.net.URL來訪問資源,當然它也支援File格式,如“file:”

取得Resource介面的執行個體 後,可以使用getFile(),getInputStream()等方法來操作資源檔

Resource 介面的案例只是資源檔一個抽象代表,指定的資源有可能不存在,可以使用exists()進行測試。

 

先看一下Resource介面的定義:一下見這個串連: Spring中的Resource介面 http://blog.csdn.net/myyate/archive/2007/10/10/1818714.aspx

定義檔案存取: 

Resource resource = new ClassPathResource("bean.xml");

BeanFactory factory = new XmlBeanFactory(resource);

HelloBean hello = (HelloBean) factory.getBean("helloBean");

這上面的ClassPathResource可以為FileSystemResource,InputStreamResource,ServletContextresource,URLResource;

  • 一個定義檔案的載入,如下:

// bean.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC  "-//SPRING/DTD BEAN/EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

    <bean id="helloBeanOfJustin" class="onlyfun.caterpillar.HelloBean">

        <property name="helloWord"><value>Hello!Justin!</value></property>

    </bean>

    <bean id="helloBeanOfcaterpillar" class="onlyfun.caterpillar.HelloBean">

        <property name="helloWord"><value>Hello!caterpillar!</value></property>

    </bean>

</beans>

操作:

Resource resource = new ClassPathResource("bean.xml");

ListableBeanFactory factory = new XmlBeanFactory(resource);

Map helloBeans = factory.getBeansOfType(HelloBean.class, false, false);

  • 多個定義檔案的載入:

BeanDefinitionRegistry reg = new DefaultListableBeanFactory();

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(reg);

//載入bean  

reader.loadBeanDefinitions(new ClassPathResource("bean1.xml"));

reader.loadBeanDefinitions(new ClassPathResource("bean2.xml"));

....

//取得Bean

BeanFactory bf = (BeanFactory) reg;

Object o = bf.getBean("helloBean");

需要org.springframework..beans.factory.support.BeanDefinitionRegistry

和org.springframework..beans.factory.support.DefaultListableBeanFactory.XmlBeanDefinitionReader

     Spring的創始者Rod Johnson建議使用ApplicationContext 來取代BeanFactory,在實現ApplicationContext 的類中,最常使用的大概是一下三個。    org.springframework.context.support.FileSystemXmlApplicationContext可指定XML定義檔案的相對路徑或絕對路徑來讀去定義檔案。    org.springframework.context.support.ClassPathXmlApplicationContext從Classpath設定路徑中來讀去定義檔案。    org.springframework.web.context.support.XmlWebApplicationContext在Web應用程式的檔案架構中,指定相對位置來讀去定義檔案。4.7.1. 構造application context

 

 

    application context構造器通常使用字串或字串數組作為資源(比如組成context定義的XML檔案)的定位路徑。當這樣的定位路徑沒有首碼時,指定的Resource 類型會通過這個路徑來被建立並被用來載入bean的定義,這都取決於你所指定的application context。例如,如果你使用下面的代碼來建立ClassPathXmlApplicationContext

ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");

這些Bean的定義會通過classpath載入並使用ClassPathResource。而如果你象下面這麼建立FileSystemXmlApplicationContext

ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");

這些Bean的定義會通過檔案系統從相對於當前工作目錄中被載入並使用FileSystemResource

請注意如果定位路徑使用classpath首碼或標準的URL首碼,那它就會覆蓋預設的Resource 類型(FileSystemResource)。因此下面的FileSystemXmlApplicationContext...

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");

...實際上會通過classpath載入其bean定義。然而它仍是個FileSystemXmlApplicationContext。如果後面它被當作ResourceLoader 來使用,那麼任何沒有使用首碼的路徑依然會被當作一個檔案系統路徑。

 

4.7.1.1. 建立 ClassPathXmlApplicationContext 執行個體 - 簡介

     ClassPathXmlApplicationContext 提供了多種構造方法以便於初始化。但其核心是,如果我們僅僅提供由XML檔案名稱組成的字串數組(沒有完整路徑資訊),而且提供了Class;那麼該ClassPathXmlApplicationContext就會從給定的類中抽取路徑資訊。

希望通過一個樣本把這些闡述清楚。假設有這樣的目錄結構:

 com/  foo/        services.xml        daos.xml        MessengerService.class

'services.xml''daos.xml' 中定義的bean組成的 ClassPathXmlApplicationContext 執行個體會象這樣地來執行個體化...

ApplicationContext ctx = new ClassPathXmlApplicationContext(    new String[] {"services.xml", "daos.xml"}, MessengerService.class);

欲瞭解 ClassPathXmlApplicationContext 多種構造方法的細節,請參考它的Javadocs。

4.7.2. Application context構造器中資源路徑的萬用字元

     Application context構造器中資源路徑的值可以是簡單的路徑(就像上面的那樣),即一對一映射到一個目標資源;或者可以包含特殊的"classpath*:"首碼和Ant風格的Regex(用Spring的 PathMatcher 工具來匹配)。後面的二者都可以使用萬用字元。

該機制的一個用處就是做組件類型的應用組裝。所有的組件都可以用通用的定位路徑“發布”context定義片斷,這樣當使用相同的 classpath*: 首碼建立最終的application context時,所有的組件片斷都會被自動裝入。

     請注意,這個萬用字元只在application context構造器的資源路徑中 (或直接在類的層次中使用 PathMatcher 工具時)有效,它會在構造時進行解析。這與 Resource 類型本身沒有關聯。因為同一時刻只能指向一個資源,所以不能使用 classpath*: 首碼來構造實際的Resource。<也就是不能在像這樣語句中使用classpath*:首碼, Resource resource = context.getResource("WEB-INF/conf/applicationContext-ibatis.xml")。是否?>

4.7.2.1. Ant風格的pattern

在包含Ant風格的pattern時,例如:

     /WEB-INFapplicationContext.xml     file:C:/some/pathapplicationContext.xml

解析器會進行一個預先定義的複雜的過程去試圖解析萬用字元。它根據路徑中最後一個非萬用字元片斷產生一個Resource並從中獲得一個URL。如果這個URL不是一個"jar:" URL或特定容器的變數(例如WebLogic中的 "zip:",WebSphere中的"wsjar"等等), 那麼可以從中獲得一個java.io.File,並用它從檔案系統中解析萬用字元。如果是一個jar URL,解析器可以從中取得一個 java.net.JarURLConnection,或者手工解析該jar URL, 隨後遍曆jar檔案以解析萬用字元。

4.7.2.1.1. 潛在的可移植性

如果給定的路徑已經是一個檔案URL(可以是顯式的或者是隱式的),由於基本的ResourceLoader是針對檔案系統的,那麼萬用字元一定能夠移植。

如果給定的路徑是一個classpath的位置,那麼解析器必須通過一個 Classloader.getResource() 調用獲得最後一個非萬用字元路徑片斷的URL。因為這僅僅是一個路徑的節點(不是最終的檔案),所以它並未確切定義(在 ClassLoader Javadocs裡) 此處究竟會返回什麼類型的URL。一般情況下,當classpath資源解析為一個檔案系統位置時,返回一個代表目錄的 java.io.File;當解析為jar位置時,返回某類jar URL。當然,這個操作涉及到可移植性。

如果從最後一個非萬用字元片斷中獲得一個jar URL,那麼解析器一定能從中取得一個 java.net.JarURLConnection,或者手動解析jar URL以遍曆jar檔案,從而解析萬用字元。這一操作在大多數環境中能正常工作,不過也有例外,因此我們強烈建議特定環境中的jar資源萬用字元解析應在正式使用前要經過徹底測試。

《續》

4.7.2.2.  classpath*: 首碼

當構造基於XML的application context時,路徑字串可能使用特殊的 classpath*: 首碼:

ApplicationContext ctx =    new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

此首碼表示所有與給定名稱匹配的classpath資源都應該被擷取(其中,這經常會在調用 ClassLoader.getResources(...)) 時發生),並接著將那些資源全並成最終的application context定義。

Classpath*: 的可移植性

帶萬用字元的classpath依賴於底層classloader的 getResources() 方法。現在大多數的應用伺服器提供自己的classloader實現,它們在處理jar檔案時的行為也許會有所不同。要測試 classpath*: 是否有效,可以簡單地用classloader從classpath中的jar檔案裡載入一個檔案: getClass().getClassLoader().getResources("<someFileInsideTheJar>")。針對兩個不同位置但有相同名字的檔案來運行測試。如果結果不對,那麼就查看一下應用伺服器的文檔,特別是那些可能影響classloader行為的設定。

"classpath*:"首碼也能在位置路徑的其他部分結合PathMatcher pattern一起使用,例如"classpath*:META-INFservice-context.xml

解析器會排除getResource("com/mycompany");返回的(第一個)URL。如果這個基礎包節點存在於多個classloader位置,最終要找的資源未必會被發現。因此在這種情況中最好在這個Ant風格的pattern中使用"classpath*:",這樣就會搜尋包含根包在內所有類路徑。

4.7.3.  FileSystemResource 提示

一個並沒有與 FileSystemApplicationContext 綁定的 FileSystemResource(也就是說FileSystemApplicationContext 並不是真正的ResourceLoader),會象你期望的那樣分辨絕對和相對路徑。相對路徑是相對於當前的工作目錄,而絕對路徑是相對與檔案系統的根目錄。

為了向前相容的目的,當 FileSystemApplicationContext 是個 ResourceLoader 時它會發生變化。FileSystemApplicationContext 會簡單地讓所有綁定的 FileSystemResource 執行個體把絕對路徑都當成相對路徑,而不管它們是否以反斜線開頭。也就是說,下面的含義是相同的:

ApplicationContext ctx =    new FileSystemClassPathXmlApplicationContext("conf/context.xml");
ApplicationContext ctx =    new FileSystemClassPathXmlApplicationContext("/conf/context.xml");

下面的也一樣:(雖然把它們區分開來也很有意義,但其中的一個是相對路徑而另一個則是絕對路徑)。

FileSystemXmlApplicationContext ctx = ...;ctx.getResource("some/resource/path/myTemplate.txt");
FileSystemXmlApplicationContext ctx = ...;ctx.getResource("/some/resource/path/myTemplate.txt");

實際上如果的確需要使用絕對路徑,那你最好就不要使用 FileSystemResourceFileSystemXmlApplicationContext來確定絕對路徑。我們可以通過使用 file: URL首碼來強制使用UrlResource

// actual context type doesn't matter, the Resource will always be UrlResourcectx.getResource("file:/some/resource/path/myTemplate.txt");
// force this FileSystemXmlApplicationContext to load it's definition via a UrlResourceApplicationContext ctx =    new FileSystemXmlApplicationContext("file:/conf/context.xml");
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.