Spring系列.Resource介面

程式設計師自由之路發表於2021-02-19

介面簡介

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");

相關文章