资源加载看似简单实际有些坑,需要整理下。

资源加载不只一种方式。看情况用哪一种即可。

类加载器获取资源(最基础)

不加左斜杠,表示从根路径加载,推荐:
InputStream is = this.getClass().getClassLoader().getResourceAsStream("config.properties");


加了左斜杠表示从当前类路径加载,那么文件要这个类同一目录,不推荐:
InputStream is2 = this.getClass().getResourceAsStream("/config.properties");

Resource获取资源

Resource是一个接口,最常用的实现类就是ClassPathResource

ClassPathResource实现类

ClassPathResource的定义很明确,获取类路径文件

Resource resource = new ClassPathResource("config.properties");

ResourceLoader获取资源

ResourceLoader也是一个接口,最常用的实现类是PathMatchingResourcePatternResolver

ResourceLoader最大的好处:
1、支持批量
单个用getResource(),批量用getResources()
2、切换资源来源(类路径、文件系统、网络资源)
classpath: # 类路径
file: # 文件系统

PathMatchingResourcePatternResolver实现类
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

支持批量:
Resource resource= resolver.getResource("classpath:config.properties"); // 单个
Resource[] resources = resolver.getResources("classpath:config/*.properties"); // 批量


灵活切换资源来源:
Resource classRes = resolver.getResource("classpath:config.properties"); // 类路径
Resource fileRes = resolver.getResource("file:/data/config.properties"); // 文件路径
ResourceLoader注入式写法

spring框架中可以直接注入使用,因为默认的实现就是PathMatchingResourcePatternResolver

@Autowired
private ResourceLoader resourceLoader;

public void loadConfig() {
    Resource resource = resourceLoader.getResource("classpath:config.properties");
}
new File()时的错误场景

这种写法绝对禁止,尤其是在获取resources下文件时

new File("src/main/resources/config.properties");

原因:
src/main/resources这个路径打包后会消失,src/main/java路径也会消失。

你看打包后的jar,BOOT-INF/classes下就是:

com # com文件夹,在idea编辑器中是src/main/java/com
appliation.yaml # 配置文件,在idea编辑器中是src/main/resources/application.yaml
Resource读取文本
public String importNovelsToEs() {
    log.info("开始导入所有金庸小说到ES,并进行文本划块");
    int totalChunks = 0;

    try {
        // 1. 获取 resources/novels/ 目录下的所有文件
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(resourceLoader);
        // 4. 使用 resolver 的 getResources 方法(注意使用 classpath*: 确保扫描所有资源)
        Resource[] resources = resolver.getResources("classpath*:/novels/*.txt");
        for (Resource resource : resources) {
            String fileName = resource.getFilename();
            if (fileName == null) continue;

            String bookName = fileName.replace(".txt", "");
            log.info("正在处理小说:{} ", bookName);

            // 2. 读取文件内容
            String content = readFileContent(resource);
            if (content == null || content.isEmpty()) {
                log.warn("小说《{}》内容为空,跳过", bookName);
                continue;
            }

            // 3. 执行文本划块并保存
            int chunks = processAndSaveChunks(bookName, content);
            totalChunks += chunks;
            log.info("小说《{}》处理完毕,生成 {} 个文本块", bookName, chunks);
        }

    } catch (IOException e) {
        log.error("扫描小说文件目录时发生异常", e);
        return "导入失败: " + e.getMessage();
    }

    String result = String.format("所有小说导入完成!共导入 %d 个文本块", totalChunks);
    log.info(result);
    return result;
}
拿到了Resource也就拿到了inputstream
一步式写法:
InputStream is = this.getClass().getClassLoader().getResourceAsStream("config.properties");

分开写:
this.getClass().getClassLoader().getResource("config.properties").openStream();

或者:
URL resource = this.getClass().getClassLoader().getResource("config.properties");
InputStream inputStream = resource.openStream();
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐