javascript
Spring Resource接口获取资源
1.1.1.?Resource簡介
?在Spring內部實現機制,針對于資源文件(配置的xml文件)有一個統一的接口Resource。
?
1.1.1.1.?接口定義的方法
1.exists():判斷資源文件是否存在。
2.isReadable():用于判斷對應資源的內容是否可讀。返回false肯定不可讀,true也不一定可讀。
3.isOpen():用于判斷當前資源是否代表一個已打開的輸入流,如果結果為true,則表示當前資源的輸入流不可多次讀取,而且在讀取以后需要對它進行關閉,以防止內存泄露。該方法主要針對于InputStreamResource,實現類中只有它的返回結果為true,其他都為false。
4.getURL():返回當前資源對應的URL。如果當前資源不能解析為一個URL則會拋出異常。如ByteArrayResource就不能解析為一個URL。
5.getFile():返回當前資源對應的File。如果當前資源不能以絕對路徑解析為一個File則會拋出異常。如ByteArrayResource就不能解析為一個File。
6.getInputStream():獲取當前資源代表的輸入流。除了InputStreamResource以外,其它Resource實現類每次調用getInputStream()方法都將返回一個全新的InputStream。
1.1.1.2.?接口繼承關系
?
1.1.1.3.?接口實現類
主要常用的有如下:
ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。
?
1.1.1.4.?ClassPathResource
主要應用于類路徑下的資源文件使用classLoader類加載器進行讀取使用
使用
ClassPathResource?resource?=?new??ClassPathResource("springok/bean/beanFactory.xml");
System.out.println(resource.getFilename());
源碼如下:
public?ClassPathResource(String?path,?ClassLoader?classLoader)?{
Assert.notNull(path,?"Path?must?not?be?null");
String?pathToUse?=?StringUtils.cleanPath(path);
if?(pathToUse.startsWith("/"))?{
pathToUse?=?pathToUse.substring(1);
}
this.path?=?pathToUse;
this.classLoader?=?(classLoader?!=?null???classLoader?:?ClassUtils.getDefaultClassLoader());
}
public?InputStream?getInputStream()?throws?IOException?{
InputStream?is;
if?(this.clazz?!=?null)?{
is?=?this.clazz.getResourceAsStream(this.path);
}
else?if?(this.classLoader?!=?null)?{
is?=?this.classLoader.getResourceAsStream(this.path);
}
else?{
is?=?ClassLoader.getSystemResourceAsStream(this.path);
}
if?(is?==?null)?{
throw?new?FileNotFoundException(getDescription()?+?"?cannot?be?opened?because?it?does?not?exist");
}
return?is;
}
1.1.1.5.?FileSystemResource
可用來獲取文件系統里面的資源。
源碼如下:
private?final?File?file;
?
private?final?String?path;
?
?
/**
?*?Create?a?new?{@code?FileSystemResource}?from?a?{@link?File}?handle.
?*?<p>Note:?When?building?relative?resources?via?{@link?#createRelative},
?*?the?relative?path?will?apply?<i>at?the?same?directory?level</i>:
?*?e.g.?new?File("C:/dir1"),?relative?path?"dir2"?->?"C:/dir2"!
?*?If?you?prefer?to?have?relative?paths?built?underneath?the?given?root
?*?directory,?use?the?{@link?#FileSystemResource(String)?constructor?with?a?file?path}
?*?to?append?a?trailing?slash?to?the?root?path:?"C:/dir1/",?which
?*?indicates?this?directory?as?root?for?all?relative?paths.
?*?@param?file?a?File?handle
?*/
public?FileSystemResource(File?file)?{
Assert.notNull(file,?"File?must?not?be?null");
this.file?=?file;
this.path?=?StringUtils.cleanPath(file.getPath());
}
1.1.1.6.?UrlResource
代表URL對應的資源。
源碼如下:
public?InputStream?getInputStream()?throws?IOException?{
URLConnection?con?=?this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
try?{
return?con.getInputStream();
}
catch?(IOException?ex)?{
//?Close?the?HTTP?connection?(if?applicable).
if?(con?instanceof?HttpURLConnection)?{
((HttpURLConnection)?con).disconnect();
}
throw?ex;
}
}
1.1.1.7.?ByteArrayResource
針對于字節數組封裝的資源,它的構建需要一個字節數組
源碼如下:
private?final?byte[]?byteArray;
?
private?final?String?description;
?
?
/**
?*?Create?a?new?ByteArrayResource.
?*?@param?byteArray?the?byte?array?to?wrap
?*/
public?ByteArrayResource(byte[]?byteArray)?{
this(byteArray,?"resource?loaded?from?byte?array");
}
1.1.1.8.?ServletContextResource
針對于ServletContext封裝的資源,用于訪問ServletContext環境下的資源。具體還是調用ServletContext?方法。
源碼如下:
private?final?ServletContext?servletContext;
private?final?String?path;
public?ServletContextResource(ServletContext?servletContext,?String?path)?{
//?check?ServletContext
Assert.notNull(servletContext,?"Cannot?resolve?ServletContextResource?without?ServletContext");
this.servletContext?=?servletContext;
Assert.notNull(path,?"Path?is?required");
String?pathToUse?=?StringUtils.cleanPath(path);
if?(!pathToUse.startsWith("/"))?{
pathToUse?=?"/"?+?pathToUse;
}
this.path?=?pathToUse;
}
1.1.1.9.?InputStreamResource
輸入流封裝的資源,它的構建需要一個輸入流。
源碼如下:
private?final?InputStream?inputStream;
?
private?final?String?description;
?
private?boolean?read?=?false;
public?InputStreamResource(InputStream?inputStream)?{
this(inputStream,?"resource?loaded?through?InputStream");
}
1.1.2.?通過ResourceLoader獲取資源
?在Spring里面還定義有一個ResourceLoader接口,該接口中只定義了一個用于獲取Resource的getResource(String?location)方法。它的實現類有很多,這里我們先挑一個DefaultResourceLoader來講。DefaultResourceLoader在獲取Resource時采用的是這樣的策略:首先判斷指定的location是否含有“classpath:”前綴,如果有則把location去掉“classpath:”前綴返回對應的ClassPathResource;否則就把它當做一個URL來處理,封裝成一個UrlResource進行返回;如果當成URL處理也失敗的話就把location對應的資源當成是一個ClassPathResource進行返回。
源碼如下:
public?Resource?getResource(String?location)?{
Assert.notNull(location,?"Location?must?not?be?null");
//classpath:
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?new?UrlResource(url);
}
catch?(MalformedURLException?ex)?{
//?No?URL?->?resolve?as?resource?path.
return?getResourceByPath(location);
}
}
}
測試:
@Test??
public?void?testResourceLoader()?{??
???ResourceLoader?loader?=?new?DefaultResourceLoader();??
???Resource?resource?=?loader.getResource("http://www.springok.com.");??
???System.out.println(resource?instanceof?UrlResource);?//true??
???//注意這里前綴不能使用“classpath*:”,這樣不能真正訪問到對應的資源,exists()返回false??
???resource?=?loader.getResource("classpath:test.txt");??
???System.out.println(resource?instanceof?ClassPathResource);?//true??
???resource?=?loader.getResource("test.txt");??
???System.out.println(resource?instanceof?ClassPathResource);?//true??
}
??????ApplicationContext接口也繼承了ResourceLoader接口,所以它的所有實現類都實現了ResourceLoader接口,都可以用來獲取Resource。
???????對于ClassPathXmlApplicationContext而言,它在獲取Resource時繼承的是它的父類DefaultResourceLoader的策略。
???????FileSystemXmlApplicationContext也繼承了DefaultResourceLoader,但是它重寫了DefaultResourceLoader的getResourceByPath(String?path)方法。所以它在獲取資源文件時首先也是判斷指定的location是否包含“classpath:”前綴,如果包含,則把location中“classpath:”前綴后的資源從類路徑下獲取出來,當做一個ClassPathResource;否則,繼續嘗試把location封裝成一個URL,返回對應的UrlResource;如果還是失敗,則把location指定位置的資源當做一個FileSystemResource進行返回。
1.1.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中。示例如下:
使用比較簡單如下:
public?class?ClassA?{??
//持有一個Resource屬性??
???private?Resource?resource;
}
配置文件如下:
<bean?id=""?class="">??
??????<property?name="resource">??
?????????<value>classpath:applicationContext.xml</value>??
??????</property>??
???</bean> ?
總結
以上是生活随笔為你收集整理的Spring Resource接口获取资源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Fragment与Activity传递数
- 下一篇: 文件批量传输组件作为架包使用说明