Spring中資源加載的框架
Spring對(duì)于資源加載有著一套自己的框架——Resource掷豺,Resource繼承自InputStream捞烟。
下面的是Resource的源碼:
public interface Resource extends InputStreamSource {
boolean exists();
default boolean isReadable() {
return true;
}
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();
}
-
exists()
判斷資源是否存在 -
isOpen()
判斷資源是否打開(kāi) -
isFile()
判斷資源是否是一個(gè)文件 -
getURL()
獲取資源文件的URL -
getURI()
獲取資源文件的URI -
readableChannel()
這個(gè)方法接口中有默認(rèn)實(shí)現(xiàn),返回的是ReadableByteChannel当船,這個(gè)類屬于Java的NIO中的管道题画。 -
contentLength()
獲取內(nèi)容的長(zhǎng)度,這個(gè)方法返回一個(gè)long德频,因?yàn)槲募?nèi)容可能很長(zhǎng)苍息。 -
lastModified()
這個(gè)方法返回的是最后修改時(shí)間,雖然也返回的是long壹置,但是這個(gè)數(shù)字是一個(gè)時(shí)間戳竞思。 -
createRelative(String relativePath)
這個(gè)方法根據(jù)relativePath返回一個(gè)相對(duì)與該Resource的Resource。 -
getFilename()
獲取文件的名字钞护。 -
getDescription
獲取一個(gè)對(duì)該資源的一個(gè)描述盖喷。
下面的是Resource的繼承圖:(這里只是一部分)
Resource的繼承圖.png
- WritableResource:可寫(xiě)資源接口,是Spring3.1版本新增的接口难咕,有兩個(gè)實(shí)現(xiàn)類FileSystemResource和PathResource课梳,其中PathResource是Spring4.0提供的實(shí)現(xiàn)類距辆。
- ByteArrayResource:二進(jìn)制數(shù)組表示的資源,二進(jìn)制數(shù)組資源可以在內(nèi)存中通過(guò)程序構(gòu)造惦界。
- ClassPathResource:類路徑下的資源挑格,資源以相對(duì)路徑的方式表示。
- FileSystemResource:文件系統(tǒng)資源沾歪,資源一文件系統(tǒng)的路徑表示漂彤,如D:/aaa/vvv.java
- InputStreamResource:以輸入流表示返回的資源。
- ServletContextResource:問(wèn)訪問(wèn)Web容器上下文中的資源而設(shè)計(jì)的類灾搏,負(fù)責(zé)對(duì)于Web應(yīng)用根目錄的路徑加載資源挫望。它支持以流和URL的方式訪問(wèn),在WAR解包的情況下狂窑,也可以通過(guò)File方式訪問(wèn)媳板。該類還可以直接從JAR包中訪問(wèn)資源。
- UrlResource:URL封裝了java.net.URL泉哈,它使用戶能夠訪問(wèn)任任何可以通過(guò)URL表示的資源蛉幸,如文件系統(tǒng)的資源、HTTP資源丛晦、FTP資源等奕纫。
- PathResource:Spring4.0提供的讀取資源文件的新類。Path封裝了java.net.URL烫沙、java.nio.Path匹层、文件系統(tǒng)資源,它使用戶能夠訪問(wèn)任何可以通過(guò)URL锌蓄、Path升筏、系統(tǒng)文件路徑表示的資源,如文件系統(tǒng)的資源瘸爽,HTTP資源您访、FTP資源等。
和JDK提供的File類訪問(wèn)資源比起來(lái)剪决,Spring的Resource實(shí)現(xiàn)類提供了更加便捷的訪問(wèn)方式灵汪,用戶可以根據(jù)實(shí)際的情況選擇合適的Resource訪問(wèn)資源。下面的是一個(gè)示例:
package top.mcwebsite.resource;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.WritableResource;
import java.io.*;
public class FileResourceTest {
@Test
public void testResource() throws IOException {
String filePath = "E:\\源碼\\Spring源碼閱讀\\testSpring\\src\\test\\resources\\spring.txt";
// 1. 使用系統(tǒng)的文件路徑方式加載文件
WritableResource resource1 = new PathResource(filePath);
// 2. 使用類路徑方式加載文件
Resource resource2 = new ClassPathResource("spring.txt");
// 3. 使用WritableResource接口寫(xiě)資源文件
OutputStream os = resource1.getOutputStream();
os.write("Spring是一套非常優(yōu)秀的框架".getBytes());
// 4. 使用Resource接口讀文件
InputStream in1 = resource1.getInputStream();
InputStream in2 = resource1.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in1);
byte[] bytes = new byte[1024];
bis.read(bytes);
System.out.println(new String(bytes));
System.out.println("resource1: " + resource1.getFilename());
System.out.println("resource2: " + resource2.getFilename());
}
}
隨之而來(lái)的問(wèn)題及解決
那就是Resource的選擇昼捍,這么多的Resource如何知道選擇使用哪一個(gè)识虚?Spring提供了一個(gè)強(qiáng)大的資源加載機(jī)制肢扯,妒茬,他可以通過(guò)前綴標(biāo)識(shí)加載資源,如:classpath, file等蔚晨,同時(shí)還支持使用Ant風(fēng)格的通配符乍钻。
- 資源地址的表示
地址前綴 | 示例 | 對(duì)應(yīng)的資源類型 |
---|---|---|
classpath: | classpath:top/mcwebsite/resource/bean.xml | 從類路徑中加載資源肛循,classpath:和classpath:/是等價(jià)的,都是相對(duì)于類的路徑银择。資源文件可以在標(biāo)準(zhǔn)的文件系統(tǒng)中多糠,也可以在JAR和ZIP的類包中 |
file: | file:/config/bean,xml | 使用UrlResource從文件系統(tǒng)目錄中裝載資源,可采用絕對(duì)或相對(duì)路徑 |
http:// | http://www.mcwebsite.top/bean.xml | 使用UrlResource從Web服務(wù)器中裝載資源 |
ftp:// | ftp://www.mcwebsite.top/bean.xml | 使用UrlResource從ftp服務(wù)器中裝載資源 |
沒(méi)有前綴 | com/mcwebsite/resource/bean.xml | 根據(jù)ApplicationContext的具體實(shí)現(xiàn)曹勇對(duì)應(yīng)類型的Resource |
關(guān)于classpath:和classpath:前綴浩考。如果有多個(gè)JAR包或文件系統(tǒng)路徑都擁有同一個(gè)相同的包夹孔。classpath:只會(huì)找到第一個(gè)加載的,而classpath:會(huì)掃描所有的這些JAR包及類路徑下出現(xiàn)的析孽。
Ant風(fēng)格的資源地址支持三種通配符:
- ?:匹配文件名中的一個(gè)字符
- *:匹配文件名中的多個(gè)字符
- **:匹配多層路徑搭伤。
ResourceLoader接口僅有一個(gè)getResource(String location)方法,可根據(jù)資源地址加載資源袜瞬。不過(guò)怜俐,資源地址僅支持帶資源類型前綴的表達(dá)式,不支持Ant風(fēng)格的資源路徑表達(dá)式邓尤。ResourcePatternResolver擴(kuò)展ResourceLoader接口拍鲤,定義了一個(gè)新的接口方法getResources(String locationPatern),該方法支持帶資源前綴及Ant風(fēng)格的資源路徑表達(dá)式汞扎。
import java.io.IOException;
import static org.junit.Assert.assertNotNull;
public class PatternResolverTest {
@Test
public void getResources() throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:*.xml");
assertNotNull(resources);
for (Resource resource : resources) {
System.out.println(resource.getDescription());
}
}
}