本地正常运行的Jasper路径代码部署至UAT服务器抛FileNotFoundException
问题原因分析
- 环境资源存储差异:
- 本地开发时,编译后的资源文件(如
Reports/xxx.jasper)存放在文件系统的物理目录中(比如target/classes/Reports),ResourceUtils.getFile()能直接解析到对应的文件路径。 - 部署成Jar包后,资源文件是嵌入在Jar内部的,并非独立的文件系统路径。
ResourceUtils.getFile()仅支持处理文件系统中的资源,无法识别Jar内的内嵌资源,因此抛出FileNotFoundException。
- 本地开发时,编译后的资源文件(如
- 路径拼写/大小写问题:
错误日志中显示的路径是class path resource[Report/quotation.jasper],但代码中使用的是classpath:Reports/(复数形式)。若UAT服务器是Linux/Unix系统(大小写敏感),而本地是Windows(大小写不敏感),则路径大小写或单复数不一致也会导致资源找不到。
解决办法
方法1:直接读取资源输入流(推荐)
如果业务逻辑可以通过输入流处理Jasper文件,直接用Spring的ResourceLoader或ClassPathResource获取输入流即可,无需依赖文件路径:
// 注入ResourceLoader @Autowired private ResourceLoader resourceLoader; public void processJasper(String jaspername) throws IOException { Resource resource = resourceLoader.getResource("classpath:Reports/" + jaspername); try (InputStream inputStream = resource.getInputStream()) { // 示例:加载JasperReport JasperReport jasperReport = JasperCompileManager.compileReport(inputStream); // 后续业务逻辑处理 } }
也可以直接使用ClassPathResource:
public void processJasper(String jaspername) throws IOException { ClassPathResource resource = new ClassPathResource("Reports/" + jaspername); try (InputStream inputStream = resource.getInputStream()) { // 处理逻辑 } }
方法2:复制内嵌资源到临时文件(适配必须用文件路径的场景)
如果工具类必须要求传入文件路径,可将Jar内的资源复制到系统临时文件,再使用临时文件的绝对路径:
@Autowired private ResourceLoader resourceLoader; public String getJasperTempPath(String jaspername) throws IOException { Resource resource = resourceLoader.getResource("classpath:Reports/" + jaspername); // 创建临时文件 File tempFile = File.createTempFile("jasper_temp_", ".jasper"); // 复制资源到临时文件,可使用Apache Commons IO的FileUtils或自行实现流复制 FileUtils.copyInputStreamToFile(resource.getInputStream(), tempFile); // 标记JVM退出时自动删除临时文件 tempFile.deleteOnExit(); return tempFile.getAbsolutePath(); }
注:使用该方法需引入Apache Commons IO依赖,或手动实现流复制逻辑。
额外检查项
- 确认
jaspername变量的值是否正确,避免路径拼写(单复数、大小写)错误,尤其是UAT服务器为Linux/Unix系统时,路径大小写敏感。
内容的提问来源于stack exchange,提问作者Gaur 97
相关产品推荐
相关产品推荐

