Java 透過 URL 統一抽象資源訪問,依賴 URLStreamHandler 處理不同協議(file:、http:、jar:)。但 classpath: 非標準協議,且註冊 Handler 較繁瑣,Spring 自行設計 Resource 介面封裝底層資源訪問邏輯。
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
關鍵點:
getInputStream():所有實作必須支援,讀取資源內容。getFile()、getURL():僅當資源確實存在於文件系統或可解析為 URL 時有效,否則拋出異常。createRelative():構建相對路徑資源,支援巢狀資源定位。| 實作類 | 資源來源 | 典型前綴 | 適用場景 |
|---|---|---|---|
| ClassPathResource | 類路徑 | classpath: | 讀取 src/main/resources、JAR 內資源 |
| FileSystemResource | 文件系統 | file: 或無前綴 | 訪問絕對/相對路徑文件 |
| UrlResource | 網絡/任意 URL | http:, https:, ftp: | 遠端資源、Jar 內資源(jar:file:/path!/entry) |
| ByteArrayResource | 位元組陣列 | 無 | 記憶體中二進制數據 |
| InputStreamResource | 輸入流 | 無 | 一次性流讀取,isOpen()=true |
| PathResource (Spring 5+) | NIO.2 Path | 無 | 現代文件系統 API |
ResourceLoader.getResource(String location):單一資源解析,自動識別前綴。ResourcePatternResolver.getResources(String locationPattern):支援 Ant 風格模式(classpath*:/META-INF/*.xml),批量解析。ApplicationContext 同時實作上述兩介面,可直接注入使用。@Component
public class ResourceDemo {
@Autowired private ResourceLoader loader;
@Autowired private ResourcePatternResolver resolver;
public void demo() throws IOException {
// 單一 classpath 資源
Resource res = loader.getResource("classpath:config/app.properties");
try (InputStream is = res.getInputStream()) { /* ... */ }
// 批量掃描 Mapper XML
Resource[] mappers = resolver.getResources("classpath*:/mapper/**/*.xml");
for (Resource r : mappers) {
System.out.println(r.getDescription()); // 輸出完整路徑描述
}
}
}
classpath: 前綴,確保跨環境(IDE、JAR、War)一致性。getFile(),資源可能在 JAR 內無法獲取 File 控制代碼;改用 getInputStream()。classpath*: 掃描分散在多模組的配置文件(如 MyBatis Mapper、Spring XML)。Resource 介面並註冊對應 ProtocolResolver(Spring 5+)。