天天看點

Spring Resource接口擷取資源

 在Spring内部實作機制,針對于資源檔案(配置的xml檔案)有一個統一的接口Resource。

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。

Spring Resource接口擷取資源

主要常用的有如下:

ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。

Spring Resource接口擷取資源

主要應用于類路徑下的資源檔案使用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;

可用來擷取檔案系統裡面的資源。

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

代表URL對應的資源。

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;

針對于位元組數組封裝的資源,它的建構需要一個位元組數組

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

針對于ServletContext封裝的資源,用于通路ServletContext環境下的資源。具體還是調用ServletContext 方法。

private final ServletContext servletContext;

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

if (!pathToUse.startsWith("/")) {

pathToUse = "/" + pathToUse;

輸入流封裝的資源,它的建構需要一個輸入流。

private final InputStream inputStream;

private boolean read = false;

public InputStreamResource(InputStream inputStream) {

this(inputStream, "resource loaded through InputStream");

 在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());

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

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

       對于ClassPathXmlApplicationContext而言,它在擷取Resource時繼承的是它的父類DefaultResourceLoader的政策。

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

通過上面内容的介紹,我們知道,在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>