springboot读取resources目录下文件

本文记录了一次在Java应用中处理复杂Excel报表导出时遇到的问题。当从本地的resources目录读取Excel模板在测试环境中无法正常工作,因为打包成jar后模板路径改变。解决方案包括将模板文件上传到服务器或使用ClassPathResource通过流读取。ClassPathResource的使用方法和代码示例给出,但因导出库不支持流处理,所以需要将模板文件保存到临时目录。总结了问题和解决思路,对类似问题的解决提供了参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

前言

最近的工作中遇到了复杂的excel报表导出业务,采用的是用excel模板来实现该业务(可以规避大量勾画excel格式的代码),将excel的模板放在项目的resources目录,遇到相关的一些问题及解决方案。

1.问题过程

resources目录下模板的位置:
在这里插入图片描述

在本地调试时直接用相对路径(templates/xxx.xlsx)就可以获取到对应的模板信息,调试自测过程都非常easy并愉快。
程序打包发到测试环境上,导出excel都是空模板没有任何数据,查看日志发现是在读取resources目录下的模板报错空指针,关键报错日志如下:

java.io.FileNotFoundException: class path resource [templates/scenery.xlsx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/xxx.jar!/BOOT-INF/classes!/templates/xxx.xlsx

从报错信息可以看出来打包(jar)模板的位置和打包之前位置已经不一样了,jar里面也是没有src这个目录,则相对路径去读取模板当然是拿不到的。

2. 解决方案

2.1 文件上传

将resources目录的文件上传到服务器上,不从resources目录下读取模板,有2种方式:

  1. 将文件上传到文件服务(如阿里云OSS),并获取到文件地址,通过流方式读取文件。这种方式需要额外的成本(文件服务器)。
  2. 在jar运行的服务器上创建目录并存放文件,然后程序里读取相对路径。这种方式不太推荐,不可控因素太多(如被误删、服务搬迁等)。

2.2 ClassPathResource

用ClassPathResource读取到resources目录下文件的流,具体代码如下:

            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.yml</include>
                </includes>
                <!--是否替换资源中的属性-->
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <!--是否替换资源中的属性-->
                <filtering>false</filtering>
            </resource>
            ClassPathResource resource = new ClassPathResource("templates/xxx.xlsx");
            InputStream inputStream = resource.getInputStream();

但是我excel导出是用的easyPOI,模板导出不支持流,必须得是文件的路径,具体实现的代码如下:

/**
     * 模板报表导出
     * @param type http
     * @param data 报表信息
     */
    public static void templateExcelExport(Map<String, Object> data, String type, HttpServletResponse httpServletResponse) throws IOException {
        //获取模板的位置
        ReportExcelEnum reportExcelEnum = ReportExcelEnum.valueOf(type);
        //获取项目的根目录
        String rootPath = System.getProperty("user.dir");
        //创建临时的模板存放文件
        String path = rootPath +"/" + reportExcelEnum.getValue();
        log.info("存放模板目录及模板文件::"+path);
        //判断模板是否已存放在文件中
        File file = new File(path);
        if(!file.exists()){
            log.info("不存在则创建文件:"+path);
            ClassPathResource resource = new ClassPathResource(reportExcelEnum.getValue());
            InputStream inputStream = resource.getInputStream();
            saveTempFile(inputStream,file);
            log.info("模板创建成功!");
        }
        //获取模板
        TemplateExportParams params = new TemplateExportParams(path);
        //获取到 Workbook
        Workbook workbook = ExcelExportUtil.exportExcel(params, data);
        //文件名
        String fileName = reportExcelEnum.getName() + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) + ".xlsx";
        //导出报表
        export(httpServletResponse, workbook, fileName);
    }


    private static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {
        //如果文件的目录不存在
        if(!tempFile.getParentFile().exists()){
            //创建父目录
            tempFile.getParentFile().mkdirs();
        }
        OutputStream os = new FileOutputStream(tempFile);
        byte[] b = new byte[2048];
        int length;
        while ((length = inputStream.read(b)) > 0) {
            os.write(b, 0, length);
        }
        os.flush();
        os.close();
        inputStream.close();
    }

总结

本篇记录一下读取resources目录下文件问题和解决方案,希望能帮到你。

<think>好的,我现在要解决用户的问题:如何在Spring Boot中读取resources目录下的文件。用户还希望有示例代码和教程。我需要结合用户提供的三个引用内容来构建答案。首先,我应该回忆一下Spring Boot处理资源文件的基本方法,然后看看用户提供的引用内容中有哪些有用的信息。 首先,引用1提到Spring Boot读取resources目录文件的方法,并提到了示例代码。引用2指出Spring Boot支持三种读取配置文件的方式,包括application.properties。引用3则给出了具体的代码示例,使用了ResourceUtils和FileUtil,并提到在jar包中可能无法使用某些方式。需要注意这一点,因为用户可能需要在打包后也能读取文件。 接下来,我需要整理常见的读取方法。通常,在Spring Boot中,资源文件放在src/main/resources目录下。读取方式有多种,比如使用ResourceUtils、ClassPathResource、@Value注解,或者通过ResourceLoader。此外,用户可能还需要了解如何处理在jar包中的情况,因为直接使用File可能会有问题,应该使用流来读取。 引用3中的代码示例使用了ResourceUtils.getFile("classpath:..."),但明确指出这在jar包中无法使用。因此,我需要提醒用户注意这一点,并建议使用流的方式。例如,使用ClassPathResource的getInputStream方法。 另外,引用2提到的application.properties可能是指通过@Value注入属性,但用户的问题是关于读取文件内容,而不是配置属性,所以可能需要不同的方法。不过,可以提到使用@Value来注入资源路径,但可能需要结合其他类来读取内容。 现在,我需要组织步骤,可能分为几种方法,每种方法给出示例代码,并说明适用场景和注意事项。例如: 1. 使用ClassPathResource:适用于各种环境,包括jar包。 2. 使用ResourceLoader:通过Spring的依赖注入获取资源。 3. 使用ResourceUtils.getFile:仅适用于开发环境,不适用于jar包。 4. 使用Files或Hutool工具类:简化操作,但同样需要注意jar包中的问题。 然后,针对每种方法给出代码示例,并指出优缺点。例如,ResourceUtils在开发时有效,但打包后失效,所以不推荐。而ClassPathResource和流的方式更可靠。 此外,需要提到文件路径的写法,比如"classpath:"前缀的使用,或者直接使用相对路径。例如,如果文件resources目录下,直接写文件名;如果在子目录,需要加上路径如"config/file.txt"。 还需要注意字符编码和异常处理,在示例代码中加入try-catch块,或者抛出异常。同时,如果用户使用了Hutool工具类,如FileUtil,可以展示更简洁的代码,但需要说明依赖问题。 最后,总结不同方法的适用场景,帮助用户根据实际情况选择。例如,开发阶段测试时可以用ResourceUtils,但生产环境推荐使用流的方式。 现在,检查是否覆盖了用户提供的引用内容。引用3中的代码示例使用了ResourceUtils和FileUtil,这需要被提及,并指出在jar中的限制。同时,引用1和2的内容可能更偏向配置文件,但用户的问题是关于读取文件内容,所以重点在具体文件读取方法。 可能还需要提醒用户关于资源文件的位置和Spring Boot的默认资源处理机制,确保文件正确放置在resources目录下,并且在构建时会被包含到类路径中。 总结,我需要分步骤说明不同的读取方法,每种方法的代码示例,适用场景,注意事项,并引用提供的参考资料中的相关内容。同时,生成相关问题,如处理大文件、动态读取、配置类使用等。</think>在Spring Boot中读取`resources`目录下的文件是常见需求,以下是几种常用方法及示例代码: --- ### 方法1:使用`ClassPathResource`(推荐) **特点**:适用于JAR包环境,通过流读取文件内容。 ```java import org.springframework.core.io.ClassPathResource; import java.io.InputStream; import java.nio.charset.StandardCharsets; public String readFileWithClassPathResource() throws IOException { ClassPathResource resource = new ClassPathResource("your-file.txt"); try (InputStream inputStream = resource.getInputStream()) { return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); } } ``` --- ### 方法2:使用`ResourceUtils`(仅开发环境) **特点**:简单直接,但**不适用于JAR包**,仅限本地开发测试。 ```java import org.springframework.util.ResourceUtils; import java.io.File; public String readFileWithResourceUtils() throws IOException { File file = ResourceUtils.getFile("classpath:your-file.txt"); return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); } ``` --- ### 方法3:通过`ResourceLoader`注入资源 **特点**:利用Spring依赖注入,灵活性强。 ```java import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Component; @Component public class FileReader { private final ResourceLoader resourceLoader; public FileReader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public String readFileWithResourceLoader() throws IOException { Resource resource = resourceLoader.getResource("classpath:your-file.txt"); try (InputStream inputStream = resource.getInputStream()) { return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); } } } ``` --- ### 方法4:工具类简化(如Hutool) **特点**:代码简洁,需添加依赖。 ```java import cn.hutool.core.io.resource.ClassPathResource; import cn.hutool.core.io.FileUtil; public List<String> readFileWithHutool() { ClassPathResource resource = new ClassPathResource("your-file.txt"); return FileUtil.readUtf8Lines(resource.getFile()); } ``` **依赖**: ```xml <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency> ``` --- ### 关键注意事项 1. **文件路径** - 若文件在`resources/config`目录下,路径应为`config/your-file.txt`。 - `classpath:`前缀可省略(默认从类路径根目录查找)[^2]。 2. **JAR包兼容性** 避免直接使用`File`对象,优先通过流读取(如`ClassPathResource.getInputStream()`)[^3]。 3. **异常处理** 需捕获`IOException`或在方法签名中声明`throws IOException`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ariel小葵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值