Spring Resource接口

目錄

1       Resource簡介

2       通過ResourceLoader獲取資源

3       在bean中獲取Resource的方式

 

1       Resource簡介

       在spring內部,針對於資源文件有一個統一的接口Resource表示。其主要實現類有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。Resource接口中主要定義有以下方法:

l  exists():用於判斷對應的資源是否真的存在。

l  isReadable():用於判斷對應資源的內容是否可讀。需要注意的是當其結果爲true的時候,其內容未必真的可讀,但如果返回false,則其內容必定不可讀。

l  isOpen():用於判斷當前資源是否代表一個已打開的輸入流,如果結果爲true,則表示當前資源的輸入流不可多次讀取,而且在讀取以後需要對它進行關閉,以防止內存泄露。該方法主要針對於InputStreamResource,實現類中只有它的返回結果爲true,其他都爲false。

l  getURL():返回當前資源對應的URL。如果當前資源不能解析爲一個URL則會拋出異常。如ByteArrayResource就不能解析爲一個URL。

l  getFile():返回當前資源對應的File。如果當前資源不能以絕對路徑解析爲一個File則會拋出異常。如ByteArrayResource就不能解析爲一個File。

l  getInputStream():獲取當前資源代表的輸入流。除了InputStreamResource以外,其它Resource實現類每次調用getInputStream()方法都將返回一個全新的InputStream。

 

       ClassPathResource可用來獲取類路徑下的資源文件。假設我們有一個資源文件test.txt在類路徑下,我們就可以通過給定對應資源文件在類路徑下的路徑path來獲取它,new ClassPathResource(“test.txt”)。

       FileSystemResource可用來獲取文件系統裏面的資源。我們可以通過對應資源文件的文件路徑來構建一個FileSystemResource。FileSystemResource還可以往對應的資源文件裏面寫內容,當然前提是當前資源文件是可寫的,這可以通過其isWritable()方法來判斷。FileSystemResource對外開放了對應資源文件的輸出流,可以通過getOutputStream()方法獲取到。

       UrlResource可用來代表URL對應的資源,它對URL做了一個簡單的封裝。通過給定一個URL地址,我們就能構建一個UrlResource。

       ByteArrayResource是針對於字節數組封裝的資源,它的構建需要一個字節數組。

       ServletContextResource是針對於ServletContext封裝的資源,用於訪問ServletContext環境下的資源。ServletContextResource持有一個ServletContext的引用,其底層是通過ServletContext的getResource()方法和getResourceAsStream()方法來獲取資源的。

       InputStreamResource是針對於輸入流封裝的資源,它的構建需要一個輸入流。

Java代碼  收藏代碼
  1.    
  2. public class ResourceTest {  
  3.    
  4.    /** 
  5.     * ClassPathResource可以用來獲取類路徑下的資源 
  6.     * @throws IOException 
  7.     */  
  8.    @Test  
  9.    public void testClassPath() throws IOException {  
  10.       Resource resource = new ClassPathResource("test.txt");  
  11.       String fileName = resource.getFilename();  
  12.       System.out.println(fileName);  
  13. //    resource.getFile();   //獲取資源對應的文件  
  14. //    resource.getURL(); //獲取資源對應的URL  
  15.       if (resource.isReadable()) {  
  16.          //每次都會打開一個新的流  
  17.          InputStream is = resource.getInputStream();  
  18.          this.printContent(is);  
  19.       }  
  20.    }  
  21.     
  22.    /** 
  23.     * FileSystemResource可以用來獲取文件系統裏面的資源,對於FileSystemResource而言我們 
  24.     * 可以獲取到其對應的輸出流。 
  25.     * @throws IOException 
  26.     */  
  27.    @Test  
  28.    public void testFileSystem() throws IOException {  
  29.       FileSystemResource resource = new FileSystemResource("D:\\test.txt");  
  30.       if (resource.isReadable()) {  
  31.          //FileInputStream  
  32.          printContent(resource.getInputStream());  
  33.       }  
  34.       if (resource.isWritable()) {  
  35.          //每次都會獲取到一個新的輸出流  
  36.          OutputStream os = resource.getOutputStream();  
  37.          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));  
  38.          bw.write("你好,中國!");  
  39.          bw.flush();  
  40.          if (os != null) {  
  41.             os.close();  
  42.          }  
  43.          if (bw != null) {  
  44.             bw.close();  
  45.          }  
  46.       }  
  47.    }  
  48.     
  49.    /** 
  50.     * 針對於URL進行封裝的Resource,可用來從URL獲取資源內容 
  51.     * @throws Exception 
  52.     */  
  53.    @Test  
  54.    public void testURL() throws Exception {  
  55.       UrlResource resource = new UrlResource("http://www.google.com.hk");  
  56.       if (resource.isReadable()) {  
  57.          //URLConnection對應的getInputStream()。  
  58.          printContent(resource.getInputStream());  
  59.       }  
  60.    }  
  61.     
  62.    /** 
  63.     * 針對於字節數組封裝的Resource,用來從字節數組獲取資源內容 
  64.     * @throws IOException 
  65.     */  
  66.    @Test  
  67.    public void testByteArray() throws IOException {  
  68.       ByteArrayResource resource = new ByteArrayResource("Hello".getBytes());  
  69.       //ByteArrayInputStream()  
  70.       printContent(resource.getInputStream());  
  71.    }  
  72.     
  73.    /** 
  74.     * 針對於輸入流的Resource,其getInputStream()方法只能被調用一次。 
  75.     * @throws Exception 
  76.     */  
  77.    @Test  
  78.    public void testInputStream() throws Exception {  
  79.       InputStream is = new FileInputStream("D:\\test.txt");  
  80.       InputStreamResource resource = new InputStreamResource(is);  
  81.       //對於InputStreamResource而言,其getInputStream()方法只能調用一次,繼續調用將拋出異常。  
  82.       InputStream target = resource.getInputStream();   //返回的就是構件時的那個InputStream  
  83.       //is將在printContent方法裏面進行關閉  
  84.       printContent(target);  
  85.    }  
  86.     
  87.    /** 
  88.     * 輸出輸入流的內容 
  89.     * @param is 
  90.     * @throws IOException 
  91.     */  
  92.    private void printContent(InputStream is) throws IOException {  
  93.       BufferedReader br = new BufferedReader(new InputStreamReader(is));  
  94.       String line;  
  95.       while ((line=br.readLine()) != null) {  
  96.          System.out.println(line);  
  97.       }  
  98.       if (is != null) {  
  99.          is.close();  
  100.       }  
  101.       if (br != null) {  
  102.          br.close();  
  103.       }  
  104.    }  
  105.     
  106. }  

 

 

2       通過ResourceLoader獲取資源

       在Spring裏面還定義有一個ResourceLoader接口,該接口中只定義了一個用於獲取Resource的getResource(String location)方法。它的實現類有很多,這裏我們先挑一個DefaultResourceLoader來講。DefaultResourceLoader在獲取Resource時採用的是這樣的策略:首先判斷指定的location是否含有“classpath:”前綴,如果有則把location去掉“classpath:”前綴返回對應的ClassPathResource;否則就把它當做一個URL來處理,封裝成一個UrlResource進行返回;如果當成URL處理也失敗的話就把location對應的資源當成是一個ClassPathResource進行返回。

Java代碼  收藏代碼
  1. @Test  
  2. public void testResourceLoader() {  
  3.    ResourceLoader loader = new DefaultResourceLoader();  
  4.    Resource resource = loader.getResource("http://www.google.com.hk");  
  5.    System.out.println(resource instanceof UrlResource); //true  
  6.    //注意這裏前綴不能使用“classpath*:”,這樣不能真正訪問到對應的資源,exists()返回false  
  7.    resource = loader.getResource("classpath:test.txt");  
  8.    System.out.println(resource instanceof ClassPathResource); //true  
  9.    resource = loader.getResource("test.txt");  
  10.    System.out.println(resource instanceof ClassPathResource); //true  
  11. }  

 

       ApplicationContext接口也繼承了ResourceLoader接口,所以它的所有實現類都實現了ResourceLoader接口,都可以用來獲取Resource。

       對於ClassPathXmlApplicationContext而言,它在獲取Resource時繼承的是它的父類DefaultResourceLoader的策略。

       FileSystemXmlApplicationContext也繼承了DefaultResourceLoader,但是它重寫了DefaultResourceLoader的getResourceByPath(String path)方法。所以它在獲取資源文件時首先也是判斷指定的location是否包含“classpath:”前綴,如果包含,則把location中“classpath:”前綴後的資源從類路徑下獲取出來,當做一個ClassPathResource;否則,繼續嘗試把location封裝成一個URL,返回對應的UrlResource;如果還是失敗,則把location指定位置的資源當做一個FileSystemResource進行返回。

 

3       在bean中獲取Resource的方式

       通過上面內容的介紹,我們知道,在bean中獲取Resource主要有以下幾種方式:

       1.直接通過new各種類型的Resource來獲取對應的Resource。

       2.在bean裏面獲取到對應的ApplicationContext,再通過ApplicationContext的getResource(String path)方法獲取對應的Resource。

     3.直接創建DefaultResourceLoader的實例,再調用其getResource(String location)方法獲取對應的Resource。

       4.通過依賴注入的方式把Resource注入到bean中。示例如下:

 

類ClassA:

Java代碼  收藏代碼
  1. public class ClassA {  
  2.    
  3.    //持有一個Resource屬性  
  4.    private Resource resource;  
  5.     
  6.    public void printContent() {  
  7.       if (resource != null && resource.exists()) {  
  8.          if (resource.isReadable()) {  
  9.             InputStream is;  
  10.             try {  
  11.                 is = resource.getInputStream();  
  12.                 BufferedReader br = new BufferedReader(new InputStreamReader(is));  
  13.                 String line;  
  14.                 while ((line=br.readLine()) != null) {  
  15.                    System.out.println(line);  
  16.                 }  
  17.                 if (is != null) {  
  18.                    is.close();  
  19.                 }  
  20.                 if (br != null) {  
  21.                    br.close();  
  22.                 }  
  23.             } catch (IOException e) {  
  24.                 e.printStackTrace();  
  25.             }  
  26.          }  
  27.       }  
  28.    }  
  29.     
  30.    public void setResource(Resource resource) {  
  31.       this.resource = resource;  
  32.    }  
  33.     
  34. }  

 

applicationContext.xml文件:

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"   
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"   
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  5.          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  6.          http://www.springframework.org/schema/context   
  7.          http://www.springframework.org/schema/context/spring-context-3.0.xsd">   
  8.    
  9.    <bean id="classA" class="com.xxx.ClassA">  
  10.       <property name="resource">  
  11.          <value>classpath:applicationContext.xml</value>  
  12.       </property>  
  13.    </bean>  
  14.    
  15. </beans>  

 

       從上面可以看到我們有一個類ClassA,其持有一個Resource屬性,在Spring bean配置文件中我們直接給ClassA注入了屬性resource。其對應的測試代碼如下:

Java代碼  收藏代碼
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration("classpath:applicationContext.xml")  
  3. public class Test1 {  
  4.    
  5.    @Autowired  
  6.    private ClassA classA;  
  7.     
  8.    @Test  
  9.    public void test() {  
  10.       classA.printContent();  
  11.    }  
  12.     
  13. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章