Spring Boot以jar包部署时如何读取static目录下的静态资源文件
问题根源
- 首次出现
FileNotFoundException的原因:src/main/resources是开发阶段的源码目录,Maven/Gradle构建打包时,该目录下的文件会被编译拷贝到Spring Boot可执行Jar的BOOT-INF/classes/路径下,Jar包内部不存在src目录结构,用FileInputStream直接读取磁盘路径必然找不到文件。 - 后续加载
.jasper失败的原因:Jar包是压缩归档文件,内部的资源不能直接通过操作系统的文件路径访问,你大概率还是沿用了文件流的方式读取静态资源目录下的文件,没有使用类路径资源加载的方式读取。
正确实现方案
1. 调整资源存放路径
把提前编译好的.jasper文件放在src/main/resources/reports目录即可,无需放在static目录(static一般用于存放可对外暴露的前端访问资源,后端内部使用的资源单独建目录管理更清晰)。
2. 使用类路径方式加载资源
Spring Boot项目推荐直接注入ResourceLoader加载类路径资源,示例代码如下:
import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.util.JRLoader; // 构造注入ResourceLoader private final ResourceLoader resourceLoader; public ReportService(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public void exportPdf() { // 读取类路径下的.jasper文件 Resource resource = resourceLoader.getResource("classpath:reports/Invoice.jasper"); try (InputStream inputStream = resource.getInputStream()) { JasperReport jasperReport = (JasperReport) JRLoader.loadObject(inputStream); // 后续填充数据、导出PDF逻辑 } catch (Exception e) { // 异常处理逻辑 e.printStackTrace(); } }
如果不想依赖Spring的ResourceLoader,也可以直接用JDK类加载器读取:
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("reports/Invoice.jasper");
注意路径不要加前缀/,直接从类路径根目录写相对路径即可。
额外注意项
- 提前编译
.jrxml是更合适的生产环境方案,可避免运行时编译的性能开销和依赖缺失问题。 - 确认你的构建工具(Maven/Gradle)没有排除
.jasper后缀的文件,默认配置下resources目录下所有文件都会被打进Jar,如果自行修改过资源过滤规则,需要确认包含.jasper格式文件。
内容的提问来源于stack exchange,提问作者Nicolas400
相关产品推荐
相关产品推荐

