Spring Resource 资源抽象

org.springframework.core.io.Resource 是 Spring 对底层资源的统一抽象接口,屏蔽了文件系统、classpath、URL、ServletContext 等不同来源的差异。

一、Resource 接口

核心方法:

方法作用
exists()资源是否存在
getInputStream()打开输入流
getFile()获取 java.io.File 句柄
getURI() / getURL()获取 URI/URL 标识
getFilename()获取文件名
contentLength() / lastModified()元信息

常用实现类:

实现类来源前缀
ClassPathResourceclasspathclasspath:
FileSystemResource文件系统file:
UrlResource任意 URLhttp: ftp:
ServletContextResourceWeb 应用根目录
ByteArrayResource内存字节数组
InputStreamResource输入流(一次性)

二、ResourceLoader 接口

核心方法:Resource getResource(String location),根据前缀决定返回哪种 Resource 实现。

Spring 中 ApplicationContext 实现了 ResourceLoader,可直接注入使用:

@Autowired
private ResourceLoader resourceLoader;  // 或直接注入 ApplicationContext
 
Resource r1 = resourceLoader.getResource("classpath:data/config.json");
Resource r2 = resourceLoader.getResource("file:/opt/app/conf.yml");

三、ResourcePatternResolver — 批量模式匹配

ResourceLoader 一次只能加载一个资源。ResourcePatternResolver 是其子接口,支持 Ant 风格通配符批量扫描:

public interface ResourcePatternResolver extends ResourceLoader {
    Resource[] getResources(String locationPattern) throws IOException;
}
通配符含义
?匹配单个字符
*匹配单层任意字符
**匹配多层路径
classpath*:扫描所有 JAR 和 classpath 目录

classpath: vs classpath*:

// classpath:  — 只扫描第一个匹配的 classpath 根
resolver.getResources("classpath:META-INF/spring.factories");
 
// classpath*: — 扫描所有 classpath 根(所有 JAR + 目录),合并返回
resolver.getResources("classpath*:META-INF/spring.factories");

四、完整体系图

ResourceLoader            (接口: getResource 单个加载)
    └── ResourcePatternResolver   (子接口: getResources 批量加载 + Ant通配符)
            └── PathMatchingResourcePatternResolver (默认实现)

ApplicationContext  实现了 ResourcePatternResolver

Resource                  (接口: 统一资源抽象)
    ├── ClassPathResource
    ├── FileSystemResource
    ├── UrlResource
    ├── ServletContextResource
    └── ByteArrayResource / InputStreamResource

常见用法

// 读取资源内容
Resource res = resourceLoader.getResource("classpath:sql/init.sql");
String sql = StreamUtils.copyToString(res.getInputStream(), StandardCharsets.UTF_8);
 
// 批量扫描 MyBatis Mapper XML
Resource[] mapperLocations = resolver.getResources("classpath*:mapper/**/*.xml");
 
// 条件判断资源是否存在
Resource res = resourceLoader.getResource("classpath:banner.txt");
if (res.exists()) { /* 自定义启动 banner */ }

参考链接