介面簡介
JDK中提供了java.net.URL這個類來用於獲取不同種類的資源(根據不同字首的url可以獲取不同種類的資源)。但是URL這個類沒有獲取classpath和ServletContext下的資源的能力。因此Spring提供了Resource介面,用於獲取各種資源。
Resource介面
spring中的org.springframework.core.io.Resource介面代表著物理存在的任何資源,其繼承於org.springframework.core.io.InputStreamSource。
Spring的資源介面是一個更強大的介面,用於抽象對低階資源的訪問。
Resource介面的主要方法如下:
public interface Resource extends InputStreamSource {
boolean exists();
default boolean isReadable() {
return exists();
}
default boolean isOpen() {
return false;
}
default boolean isFile() {
return false;
}
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
default ReadableByteChannel readableChannel() throws IOException {
return Channels.newChannel(getInputStream());
}
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
@Nullable
String getFilename();
String getDescription();
}
關於上面提供的getURI和getURL方法這邊做下解釋。URI用於唯一指定網際網路上一個資源的名字,我們可以理解為一個資源的唯一id。URL代表一個資源的唯一地址,我們通過這個地址可以在網際網路上尋找到這個資源。通常可以用URL來代替URI。
Resource繼承了InputStreamSource介面,下面是其定義:
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
Resource的比較重要的方法如下:
- getInputStream(): 定位和開啟resource, 返回InputStream 來讀取資源。每一次呼叫都會返回一個新的InputStream,呼叫者負責將其關閉。
- exists(): 返回boolean,用來判斷資源是否存在
- isOpen(): 返回boolean,用來判斷資源是不是已經存在一個open stream處理器。 true表明InputStream不能被多次讀取,那麼這次的讀取會被關閉,以避免資源洩露。false是所有正常資源實現的返回,有可能會拋異常:InputStreamResource。
- getDescription(): 返回資源的描述,用於錯誤輸出。通常這會返回resource URL的全名。
其他的方法可以讓你獲取到代表resource的URL或者File物件。
Resource介面在Spring程式碼中非常常用,你也可以考慮應用到你的程式中。
內建的Resource實現
Spring中提供了很多Resource介面的實現類。主要有ByteArrayResource, ClassPathResource, DescriptiveResource, FileSystemResource, InputStreamResource, PortletContextResource, ServletContextResource和UrlResource。常用的有:
- ClassPathResource:通過 ClassPathResource 以類路徑的方式進行訪問;
- FileSystemResource:通過 FileSystemResource 以檔案系統絕對路徑的方式進行訪問;
- ServletContextResource:通過 ServletContextResource 以相對於Web應用根目錄的方式進行訪問。
- UrlResource :通過java.net.URL來訪問資源,當然它也支援File格式,如“file:”、“http:”。
ResourceLoader介面
ResourceLoader介面用來載入Resource資源。
public interface ResourceLoader {
Resource getResource(String location);
}
所有的ApplicationContext類都實現了ResourceLoader介面,所以我們可以使用context來載入resource。
不同型別的ApplicationContext會返回不同的Resource。
當你在特定的應用程式上下文上呼叫getResource(),並且指定的位置路徑沒有特定的字首時,你將返回適合該特定應用程式上下文的資源型別。例如,假設對ClassPathXmlApplicationContext例項執行了以下程式碼片段:
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
ClassPathXmlApplicationContext返回ClassPathResource,FileSystemXmlApplicationContext返回FileSystemResource,WebApplicationContext返回ServletContextResource。 他會返回和ApplicationContext相對應的Resource實現。
當然,你可以強制ClassPathResource使用,而不管ApplicationContext到底是什麼。使用的方法就是在資源路徑前面加字首。
Resource template1 = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
Resource template2 = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
Resource template3 = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource[] template4 = ctx.getResources("file:///some/resource/path/my**a.txt");
ResourceLoaderAware介面
ResourceLoaderAware介面是一個特殊的回撥介面,表明該元件需要提供一個ResourceLoader的引用。 下面是ResourceLoaderAware的定義:
public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}
一個Bean如果實現了ResourceLoaderAware介面,容器在載入Bean的時候會給這個Bean注入一個ResourceLoad實現類(容器設定的ResourceLoad就是容器本身,因為所有的Spring application contexts 都實現了ResourceLoader 介面),利用這個實現類也可以載入Resource資源。
Resources as Dependencies
不知道在講什麼,後續再整理。。。
構造 ApplicationContext
//從classpath下尋找配置檔案構造ApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
//從當前工作目錄尋找配置檔案構造FileSystemXmlApplicationContext
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
//由於加了classpath字首,所以從classpath下尋找配置構造FileSystemXmlApplicationContext
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
//以MessengerService類所在的路徑為基準路徑,尋找services.xml和daos.xml作為配置檔案
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}, MessengerService.class);
萬用字元形式構造資源
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");