Spring Boot Maven打包Jar无法定位src/main/resources下文件
报错的核心原因是代码硬编码了开发环境的源码相对路径src\main\resources\extent-config.xml读取文件。
本地IDE独立运行时,程序工作目录默认是项目根目录,这个相对路径能匹配到源码目录下的文件,所以运行正常。但Spring Boot打为可执行Jar包后,src/main/resources下的所有文件会被直接复制到Jar包内的BOOT-INF/classes/路径下(也就是classpath根路径),Jar包本身是压缩包而非磁盘上的真实目录,不存在src/main/resources这个文件系统路径,用磁盘文件路径的方式读取必然报找不到文件。
从提供的Jar结构截图可以确认,extent-config.xml已经正常被打进包内,不属于打包漏资源的问题。
优先使用Classpath流读取资源(符合Spring Boot开发规范,无跨环境兼容问题)
全局搜索代码中所有写死src/main/resources或src\main\resources的路径前缀,全部替换为classpath读取方式:- Java原生API读取方式:
// 注意路径最前面加/,代表从classpath根目录查找,*不要带src/main/resources前缀* InputStream configStream = getClass().getResourceAsStream("/extent-config.xml");- Spring工具类读取方式:
ClassPathResource configResource = new ClassPathResource("extent-config.xml"); InputStream configStream = configResource.getInputStream();你使用的ExtentReports的
XmlConfigLoader支持直接传入InputStream参数,不要把路径字符串传给它,直接传入上面获取到的流对象即可,避免其内部按磁盘文件路径查找资源。兼容方案(仅适配必须接收文件路径的老逻辑,不推荐优先使用)
如果用到的第三方API只支持传入磁盘文件路径、不支持流传入,可以在项目启动时先把Jar包内的配置文件复制到外部临时目录,再用临时文件的绝对路径传入:ClassPathResource configResource = new ClassPathResource("extent-config.xml"); File tempConfig = File.createTempFile("extent-config", ".xml"); tempConfig.deleteOnExit(); try (InputStream source = configResource.getInputStream(); OutputStream target = new FileOutputStream(tempConfig)) { FileCopyUtils.copy(source, target); } // 后续使用tempConfig.getAbsolutePath()作为配置路径传入加载逻辑
- 检查代码中是否存在Windows风格的路径分隔符
\硬编码,跨环境部署(比如Jar包跑在Linux服务器上)时,\无法被识别为路径分隔符,统一用Classpath读取可以规避这个问题。 - 你当前pom.xml中的resources配置、spring-boot-maven-plugin配置没有问题,不需要修改打包规则。
内容的提问来源于stack exchange,提问作者Abhi

