Maven父子模块项目中如何正确指定文件相对路径?
解决Maven多模块项目中资源文件路径加载问题
你的问题本质是混淆了开发时的文件系统路径和运行时的类路径——本地IDE运行时默认工作目录是项目根目录de-service,所以你写的相对路径能找到文件;但部署后,程序的工作目录变成了de-service-web模块的运行目录,而且Maven打包后资源文件已经被整合到classpath中,不再是原来的文件系统路径了。
下面是两种可靠的解决方案,优先推荐第一种:
1. 使用类路径加载资源(强烈推荐)
因为testModel.model位于de-service-web/src/main/resources/model/下,Maven打包时会自动把这个目录下的文件复制到target/classes/model/,最终会被打包到jar/war的classpath根目录下的model文件夹里。所以你可以通过类加载器直接读取这个资源,完全不用关心文件系统的具体路径:
普通Java项目示例
// 方式1:通过当前类的类加载器读取(适合非静态方法) InputStream modelStream = getClass().getResourceAsStream("/model/testModel.model"); if (modelStream == null) { throw new FileNotFoundException("无法在classpath中找到testModel.model"); } // 后续通过modelStream处理文件内容,比如读取为字符串或字节数组 // 方式2:通过上下文类加载器读取(更灵活,适合静态方法) InputStream modelStream2 = Thread.currentThread().getContextClassLoader() .getResourceAsStream("model/testModel.model");
小提示:
getClass().getResourceAsStream()的路径如果以/开头,是相对于classpath根;如果不带/,是相对于当前类所在的包路径。而上下文类加载器的路径默认就是相对于classpath根,所以不用加开头的/。
Spring/Spring Boot项目示例
如果你的项目是Spring相关的,可以用ClassPathResource来简化操作:
ClassPathResource resource = new ClassPathResource("model/testModel.model"); // 注意:如果资源在jar包内,不要用getFile()(会抛出IO异常),优先用getInputStream() InputStream modelStream = resource.getInputStream();
2. 不推荐:通过工作目录拼接路径(仅适用于特殊场景)
如果你一定要用文件系统路径(非常不建议,因为部署环境的工作目录可能和本地完全不一致),可以先获取当前程序的工作目录,再拼接相对路径:
String userDir = System.getProperty("user.dir"); // 假设部署后工作目录是de-service-web,拼接路径 String modelPath = userDir + "/src/main/resources/model/testModel.model"; // 但这种方式极其不可靠——比如打包成jar后,服务器上根本不存在src目录
为什么原来的路径会失效?
- 本地IDE运行时,默认工作目录是项目根
de-service,所以de-service-web/src/main/resources/model/testModel.model是有效的文件系统路径。 - 部署到服务器后,程序的工作目录可能是
de-service-web模块的目录,或者已经打包成jar/war,此时原来的文件系统路径已经不存在,资源已经被嵌入到包内的classpath中,只能通过类加载器读取。
内容的提问来源于stack exchange,提问作者user697911
相关产品推荐
相关产品推荐

