当前位置: 首页 > news >正文

[spring6: Resource ResourceLoader ResourceEditor]-加载资源

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

ResourcePatternResolverResourceLoader 的扩展接口,提供了通过模式(如 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;}}}
http://www.xdnf.cn/news/1122661.html

相关文章:

  • 【Java笔记】七大排序
  • 现有医疗AI记忆、规划与工具使用的创新路径分析
  • 融合竞争学习与高斯扰动的多目标加权平均算法(MOWAA)求解多无人机协同路径规划(多起点多终点,起始点、无人机数、障碍物可自定义),提供完整MATLAB代码
  • 嵌入式硬件篇---晶体管的分类
  • Transformer江湖录 第五章:江湖争锋 - BERT vs GPT
  • ZYNQ双核通信终极指南:FreeRTOS移植+OpenAMP双核通信+固化实战
  • CSS面试题
  • C++卸载了会影响电脑正常使用吗?解析C++运行库的作用与卸载后果
  • 后端接口通用返回格式与异常处理实现
  • UI前端大数据处理新挑战:如何高效处理实时数据流?
  • JavaScript学习第九章-第三部分(内建对象)
  • 内测分发平台应用的异地容灾和负载均衡处理和实现思路
  • 8.服务通信:Feign深度优化 - 解密声明式调用与现代负载均衡内核
  • 【微信小程序】
  • SQL ORM映射框架深度剖析:从原理到实战优化
  • springboot 好处
  • 【日常技能】excel的vlookup 匹配#N/A
  • 如何将 iPhone 备份到云端:完整指南
  • Mysql数据库学习--多表查询
  • spring-ai-alibaba官方 Playground 示例之联网搜索代码解析
  • 力扣 hot100 Day44
  • 判断端口处于监听状态的方法
  • day40 训练和测试的规范写法
  • 手滑误操作? vue + Element UI 封装二次确认框 | 附源码
  • ThinkPHP 8 在 Apache 下启用伪静态
  • 机器学习(ML)、深度学习(DL)、强化学习(RL):人工智能的三驾马车
  • Spring的`@Value`注解使用详细说明
  • 企业培训笔记:axios 发送 ajax 请求
  • 2025/7/14——java学习总结
  • Linux多进程