文章目录
内置 Resource 接口实现
ResouceUtils
ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 xx.class.getClassLoader().getResouceAsStream()这种以流的形式读取文件的方式,所以使用读取文件流就可以拿到了。
UrlResource
UrlResource 封装了 java.net.URL,可用于访问通过 URL 访问的任何对象,比如文件、HTTP 资源、FTP 资源等等。所有 URL 都有一个标准化的字符串表示,因此可以使用适当的标准化前缀来表示不同 URL 类型的 URL。一般支持如下资源访问。
new UrlResource("file:d/xxx.txt");
new UrlResource("http://地址");
new UrlResource("ftp://地址");
ClassPathResource
ClassPathResource 表示从类路径获取资源,它使用线程上下文类加载器、给定的类加载器来加载资源。classpath 资源存在于类路径中的文件系统中或 jar 包里。
ClassPathResource 常用构造器
public ClassPathResource(String path);
public ClassPathResource(String path, @Nullable ClassLoader classLoader);
public ClassPathResource(String path, @Nullable Class<?> clazz);
public ClassPathResource(String path):使用默认的类加载器记载 path 类路径下的资源
public ClassPathResource(String path, @Nullable ClassLoader classLoader):使用指定的类加载器加载 path 类路径下的资源
public ClassPathResource(String path, @Nullable Class clazz):只用指定的类加载 path 类路径下的资源
FileSystemResource
FileSystemResource 是 Resource 实现支持 java.io 和 java.nio.file.Path 的处理。
ServletContextResource
ServletContextResource 是 web 应用资源,ServletContext 资源的实现。用于简化 servlet 容器的 ServletContext 接口的 getResource 操作和 getResourceAsStream 操作。
InputStreamResource
InputStreamResource 是基于 InputStream 的实现,参数是一个 InputStream 只有在没有特定场景下的 Resource 的时候才使用它。
ByteArrayResource
ByteArrayResource 是给定一个 byte[] 数组的实现创建 ByteArrayInputStream。
ResourceLoader
ResourceLoader 用于返回 Resource 的实例。
public interface ResourceLoader {
Resource getResource(String location);
}
Spring 的 ApplicationContext 都实现了 ResourceLoader
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- WebApplicationContext
因此可以使用 ApplicationContext 来获取资源实例,当在某个 ApplicationContext 实现类中调用 getResource 而参数没有指定特定的资源前缀时,将返回适合 ApplicationContext 实现实例的资源类型,下面是 ClassPathXmlApplicationContext 的执行代码
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
对于 ClassPathXmlApplicationContext 以上代码返回一个 ClassPathResource。
如果对 FileSystemXmlApplicationContext 实例执行相同的方法,它将返回FileSystemResource。对于 WebApplicationContext,它将返回一个 ServletContextResource。
另外也可以指定资源前缀比如 classpath: 强制使用 ClassPathResource 无论 ApplicationContext 实现实例类型是什么。
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
也可以使用其他前缀
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");
getResource 字符串参数对象转换为资源对象的策略
| 资源前缀 | 示例 | 说明 |
|---|---|---|
| classpath: | classpath:com/myapp/config.xml | 从 classpath 类路径加载 |
| file: | file:///data/config.xml | 从文件系统中作为 URL 加载 |
| http: | https://myserver/logo.png | 作为 URL 加载 |
| (none) | /data/config.xml | 根据 ApplicationContext 实现实例加载 |
classpath 和 classpath 区别*
classpath:用于加载类路径(包括jar包)中的一个且仅一个资源;对于多个匹配的也只返回一个。
classpath* :用于加载类路径(包括jar包)中的所有匹配的资源。
问题
1、如何获取 SpringBoot jar 包中的指定文件夹下的资源文件子目录?
借助 Spring 提供的 PathMatchingResourcePatternResolver 类得以解决。
2、获取文件路径时 resource.getFile().getPath() 为啥出现 FileNotFoundException?
SpringBoot 没办法通过 File 的形式访问 jar 包里面的文件,借助 resource.getURL().getPath() 获取当前资源对应的URL的路径得以解决。
3、若已知道要加载的资源文件的名称与目录,该怎么加载呢?
Xxx.getClass().getResourceAsStream(“”)
例子
private static final String EXTENSIN_KEY = "key";
private static final String EXTENSIN_PROPERTIES = "properties";
public static boolean initEnv() {
try {
Map<String, Map<String, InputStream>> resourceMap = Maps.newHashMap();
// 1. 定义资源匹配规则,会在所有的JAR包的根目录下搜索指定文件
String matchPattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "/cool/*/*.*";
// 2. 返回指定路径下所有的资源对象(子目录下的资源对象)
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resourcePatternResolver.getResources(matchPattern);
for (Resource resource : resources) {
// 3. 获取文件名称
String fileFlag = resource.getFilename().endsWith(EXTENSIN_KEY) ? EXTENSIN_KEY : EXTENSIN_PROPERTIES;
// 4. 获取子目录名称
String[] filePathAry = resource.getURL().getPath().split("/");
String mb = filePathAry[filePathAry.length - 2];
Map<String, InputStream> mbMap = resourceMap.get(mb);
if (MapUtils.isEmpty(mbMap)) {
mbMap = Maps.newHashMap();
resourceMap.put(mb, mbMap);
}
mbMap.put(fileFlag, resource.getInputStream());
}
// 5. 封装资源文件流的Map
Map<InputStream, InputStream> map = Maps.newHashMap();
resourceMap.forEach((mainBody, inputStreamMap) -> {
map.put(inputStreamMap.get(EXTENSIN_KEY), inputStreamMap.get(EXTENSIN_PROPERTIES));
});
} catch (Exception e) {
return false;
}
// ... ...
// 采用 map 进行后续特殊操作(省略)
// ... ...
return true;
}
本文详细介绍了Spring中Resource接口的实现类及其用途,如UrlResource、ClassPathResource、FileSystemResource等,以及如何通过ResourceLoader加载资源。针对在Spring Boot jar包中获取资源文件子目录、处理FileNotFoundException等问题,提出了解决方案,例如使用PathMatchingResourcePatternResolver。同时,文章还展示了如何根据已知文件名和目录加载资源,并给出了示例代码。
4175

被折叠的 条评论
为什么被折叠?



