Maven相对路径读取资源最佳实践及实际场景问题咨询
Maven资源读取问题解答
两个方案的错误原因
方案1错误点
${project.basedir}是Maven POM文件的内置属性,仅能在POM配置、Maven插件执行上下文中使用,不属于Java运行时可识别的语法或变量。你直接将其写在Java代码中,会触发编译错误,Java编译器无法识别${}语法,也不存在内置的project对象供你调用getBasedir()方法。
方案2错误点
- 打包后资源存放在jar包内部,
getResource()返回的URL格式为jar:file:/xxx.jar!/内部路径,这种路径属于压缩包内的资源定位符,不能直接转换为File对象,File只能读取操作系统文件系统中存在的独立实体文件,无法识别jar包内部的条目。 - 默认配置下
src/test/resources下的资源仅会在单元测试运行时加入类路径,执行mvn package打包生成的jar包仅会包含src/main/resources下的内容,你将资源放在test目录下,正式运行jar包时类路径中根本没有该资源。
符合Maven规范的实现方案
场景1:资源为生产代码运行时使用
- 先将
paramsGeneral.txt从src/test/resources/com/moga/planning/移动到src/main/resources/com/moga/planning/目录下,与调用类RunCapacityPlanning的包路径保持一致。 - 直接通过类加载器读取资源流,不要用
File对象包装:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; public class RunCapacityPlanning { public static void main(String[] args) { // 同包路径下的资源直接写文件名即可 try (InputStream inputStream = RunCapacityPlanning.class.getResourceAsStream("paramsGeneral.txt")) { if (inputStream == null) { System.out.println("资源不存在"); return; } // 读取资源内容 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); String line; while ((line = reader.readLine()) != null) { // 处理文件内容逻辑 System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } }
如果需要用类路径绝对路径定位资源,路径以/开头即可:RunCapacityPlanning.class.getResourceAsStream("/com/moga/planning/paramsGeneral.txt"),和上面的写法效果完全一致。
场景2:资源仅为单元测试使用
不需要移动资源文件,保持在src/test/resources/com/moga/planning/下即可,单元测试代码直接使用上述getResourceAsStream的写法就能正常读取,Maven执行单元测试时会自动将test/resources下的内容加入类路径。
特殊需求:将test目录下的资源打包到生产jar
如果确实需要把src/test/resources的内容打包到正式jar包中,可以修改POM的build配置:
<build> <resources> <resource> <directory>src/main/resources</directory> </resource> <resource> <directory>src/test/resources</directory> </resource> </resources> <!-- 原有其他build配置 --> </build>
该方案不推荐,会导致测试相关资源混入生产包,仅作为临时兼容方案使用。
原有临时方案的问题
你当前用System.getProperty("user.dir")拼接项目源码路径的写法,仅在项目根目录下运行代码时生效,一旦把jar包移动到其他目录运行,没有对应的src目录结构,就会读取失败,通用性极差,不建议长期使用。
内容的提问来源于stack exchange,提问作者dtkx
相关产品推荐
相关产品推荐

