Resource
Resource
接口為處理和訪問不同類型資源(如文件、URL、輸入流等)提供了統一的 API,支持資源的存在性檢查、讀取、轉換等操作。
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());}default byte[] getContentAsByteArray() throws IOException {return FileCopyUtils.copyToByteArray(getInputStream());}default String getContentAsString(Charset charset) throws IOException {return FileCopyUtils.copyToString(new InputStreamReader(getInputStream(), charset));}long contentLength() throws IOException;long lastModified() throws IOException;Resource createRelative(String relativePath) throws IOException;@NullableString getFilename();String getDescription();}
public interface InputStreamSource {InputStream getInputStream() throws IOException;
}
實現類 | 描述 |
---|---|
UrlResource | 用于封裝 java.net.URL ,可以訪問任何通過 URL 訪問的資源,如文件、HTTPS、FTP 等。 |
ClassPathResource | 用于從類路徑加載資源,支持使用類加載器或特定類來加載資源。 |
FileSystemResource | 基于 java.io.File 的實現,支持文件系統路徑,采用 Java NIO API 進行操作。 |
PathResource | 基于 java.nio.file.Path 的實現,采用 NIO API,支持文件和 URL 解析,且實現了 WritableResource 接口。 |
ServletContextResource | 用于 ServletContext 資源,解析相對路徑并在 Web 應用的根目錄下查找資源。 |
InputStreamResource | 封裝已打開的 InputStream ,適用于流式訪問已打開的資源,避免多次讀取。 |
ByteArrayResource | 基于給定字節數組的實現,通過 ByteArrayInputStream 來加載內容,適合加載內存中的數據。 |
ResourceLoader
ResourceLoader
接口用于資源加載策略,通常在 Spring 應用中用于加載文件、類路徑或其他類型的資源。它的子接口和實現類則為其功能擴展,支持不同類型的應用上下文或資源解析需求。|
public interface ResourceLoader {/** Pseudo URL prefix for loading from the class path: "classpath:". */String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;Resource getResource(String location);@NullableClassLoader getClassLoader();}
DefaultResourceLoader
DefaultResourceLoader
是 Spring 中用于加載各種類型資源的默認實現,支持通過類路徑、文件系統、URL 等方式加載,并允許擴展協議解析器。
// Direct Known Subclasses:
// AbstractApplicationContext, ClassRelativeResourceLoader, FileSystemResourceLoader, ServletContextResourceLoader
public class DefaultResourceLoader implements ResourceLoader {@Nullableprivate ClassLoader classLoader;private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);public DefaultResourceLoader() {}public DefaultResourceLoader(@Nullable ClassLoader classLoader) {this.classLoader = classLoader;}public void addProtocolResolver(ProtocolResolver resolver) {Assert.notNull(resolver, "ProtocolResolver must not be null");this.protocolResolvers.add(resolver);}@SuppressWarnings("unchecked")public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {return (Map<Resource, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());}public void clearResourceCaches() {this.resourceCaches.clear();}@Overridepublic Resource getResource(String location) {Assert.notNull(location, "Location must not be null");for (ProtocolResolver protocolResolver : getProtocolResolvers()) {Resource resource = protocolResolver.resolve(location, this);if (resource != null) {return resource;}}if (location.startsWith("/")) {return getResourceByPath(location);}else if (location.startsWith(CLASSPATH_URL_PREFIX)) {return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {// Try to parse the location as a URL...URL url = ResourceUtils.toURL(location);return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));}catch (MalformedURLException ex) {// No URL -> resolve as resource path.return getResourceByPath(location);}}}protected Resource getResourceByPath(String path) {return new ClassPathContextResource(path, getClassLoader());}protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {super(path, classLoader);}@Overridepublic String getPathWithinContext() {return getPath();}@Overridepublic Resource createRelative(String relativePath) {String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);return new ClassPathContextResource(pathToUse, getClassLoader());}}
}
ResourcePatternResolver
ResourcePatternResolver
是 ResourceLoader
的擴展接口,提供了通過模式(如 Ant 風格路徑)解析位置并返回 Resource
對象的功能。它支持 classpath*:
前綴來獲取類路徑和模塊路徑中所有匹配的資源。
// "classpath:META-INF/config.xml" 只匹配 第一個 META-INF/config.xml
// "classpath*:META-INF/config.xml" 匹配 所有 JAR 包 和 所有 META-INF 目錄 下的 config.xml// PathMatchingResourcePatternResolver
public interface ResourcePatternResolver extends ResourceLoader {String CLASSPATH_ALL_URL_PREFIX = "classpath*:";Resource[] getResources(String locationPattern) throws IOException;}
ResourceEditor
ResourceEditor
通過繼承 PropertyEditorSupport
提供了對資源路徑的自動解析和加載功能。它能夠將字符串路徑
轉換為 Resource
類型,同時支持占位符解析和動態路徑處理。這使得資源的配置和加載變得更加靈活與便捷,尤其適用于需要根據配置或環境動態加載資源的場景。
public class ResourceEditor extends PropertyEditorSupport {private final ResourceLoader resourceLoader;@Nullableprivate PropertyResolver propertyResolver;private final boolean ignoreUnresolvablePlaceholders;public ResourceEditor() {this(new DefaultResourceLoader(), null);}public ResourceEditor(ResourceLoader resourceLoader, @Nullable PropertyResolver propertyResolver) {this(resourceLoader, propertyResolver, true);}public ResourceEditor(ResourceLoader resourceLoader, @Nullable PropertyResolver propertyResolver,boolean ignoreUnresolvablePlaceholders) {Assert.notNull(resourceLoader, "ResourceLoader must not be null");this.resourceLoader = resourceLoader;this.propertyResolver = propertyResolver;this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;}@Overridepublic void setAsText(String text) {if (StringUtils.hasText(text)) {String locationToUse = resolvePath(text).trim();setValue(this.resourceLoader.getResource(locationToUse));}else {setValue(null);}}protected String resolvePath(String path) {if (this.propertyResolver == null) {this.propertyResolver = new StandardEnvironment();}return (this.ignoreUnresolvablePlaceholders ? this.propertyResolver.resolvePlaceholders(path) :this.propertyResolver.resolveRequiredPlaceholders(path));}@Override@Nullablepublic String getAsText() {Resource value = (Resource) getValue();try {return (value != null ? value.getURL().toExternalForm() : "");}catch (IOException ex) {return null;}}}