一文看懂!Maven 工程与打包后的目录映射关系
我在 src/main/resources 下写的 application.yml,程序运行起来后到底去哪找它?为什么我的 Mapper XML 文件明明在工程里,打包后却不见了?经常听到的Classpath(类路径),到底指的是哪里?Maven 遵循“约定优于配置”的原则,但如果我们不了解这个“约定”,开发时就会踩坑。今天我们就来拆解一下 Maven 项目从源码到JAR包的映射关系。
【Maven避坑】源码去哪了?一文看懂 Maven 工程与打包后的目录映射关系
摘要:你是否遇到过 FileNotFoundException?是否遇到过 MyBatis 报错 Invalid bound statement?很多时候,这并非代码写错了,而是你没搞懂 Maven 打包时把你的文件“搬”到了哪里。本文将通过图解,带你揭开 Maven 打包的“乾坤大挪移”之谜。本文由Gemini 3.0 生成
前言
作为一个 Java 后端新人,在开发过程中,我常会有这样的困惑:
- 我在 src/main/resources 下写的 application.yml,程序运行起来后到底去哪找它?
- 为什么我的 Mapper XML 文件明明在工程里,打包后却不见了?
- 经常听到的 Classpath(类路径),到底指的是哪里?
Maven 遵循“约定优于配置”的原则,但如果我们不了解这个“约定”,开发时就会踩坑。今天我们就来拆解一下 Maven 项目从源码到JAR包的映射关系。
一、 一张图看懂核心映射
Maven 在执行 mvn package 打包时,主要做了一件事:把 src/main 下的Java 代码和资源文件,经过编译和整理,合并到了 JAR 包的根目录下。
请看下面的对比图(这是最核心的知识点):
text
【工程源码目录 (Source)】 【打包后的 JAR 内部目录 (Runtime)】 MyProject ├── src │ ├── main │ │ ├── java (Java代码) │ │ │ └── com │ │ │ └── demo │ │ │ └── User.java ---> com/demo/User.class (变成了字节码) │ │ │ │ │ └── resources (资源文件) │ │ ├── application.yml -----> application.yml (直接在根目录下!) │ │ ├── mybatis-config.xml ---> mybatis-config.xml │ │ └── mapper │ │ └── UserMapper.xml ---> mapper/UserMapper.xml │ │ │ └── test (测试代码) │ └── ... ---> (直接丢弃,不进入最终JAR包)
二、 三大映射规则
理解了上面的图,我们可以总结出 Maven 的三条打包铁律:
1. Java 目录:编译并保持结构
Maven 会调用 javac 将 src/main/java 下的 .java 文件编译成 .class 文件。 重点:包路径(package)会直接转化为文件夹路径。
- 源码:src/main/java/com/demo/User.java
- 打包后:JAR根/com/demo/User.class
2. Resources 目录:复制并“平铺”
src/main/resources 是资源的根目录。Maven 会把这个文件夹内部的所有东西,直接复制到 JAR 包的根目录下。 重点:它会和编译后的 class 文件混在一起!
- 这就是为什么我们在代码里读取配置文件时(例如 classpath:application.yml),不需要写 resources/ 前缀,因为它就在根目录下。
3. Test 目录:用完即弃
src/test 下的所有代码和资源,仅在 mvn test 阶段生效。它们绝对不会出现在最终生成的 JAR 包里。
- 避坑:千万不要在生产代码里依赖 src/test 下写的工具类。
三、 经典踩坑场景:MyBatis 的 XML 去哪了?
这是初学者最容易遇到的坑。
场景 A:XML 放在 resources 下(推荐 ✅)
如果你把 UserMapper.xml 放在 src/main/resources/mapper/ 下。 根据规则 2,打包后它位于 JAR根/mapper/UserMapper.xml。 一切正常,程序能找到。
场景 B:XML 放在 java 目录下(报错 ❌)
为了方便管理,很多人喜欢把 UserMapper.xml 和 UserMapper.java 接口放在同一个包下,例如 src/main/java/com/demo/mapper/。
后果: Maven 的默认机制是:在 src/main/java 目录下,只编译 .java 文件,忽略其他所有文件(包括 XML)。 所以,你的 JAR 包里根本没有那个 XML 文件!MyBatis 启动时自然报错。
解决方案: 如果你非要这么放,必须在 pom.xml 中配置资源过滤,告诉 Maven:“别忽略我的 XML!”
xml
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build>
四、 所谓的 Classpath 到底是什么?
理解了目录映射,Classpath 的概念就迎刃而解了。
在 Spring 或 Java 中,当我们说 classpath: 时,指的就是 打包后的 JAR 包根目录(或者在 IDE 开发时,指的是 target/classes 目录)。
- classpath:application.yml -> 去 JAR 包根目录找。
- classpath:com/demo/User.class -> 去 JAR 包根目录下的 com/demo 找。
五、 动手验证(Show me the code)
不要只听我说,建议你自己动手验证一下,印象会更深:
- 找一个 Maven 项目,执行命令 mvn package。
- 进入项目的 target 目录。
- 找到生成的 .jar 文件。
- 把后缀名从 .jar 改成 .zip,然后解压它!
打开解压后的文件夹,你会发现,所谓的“神秘”目录结构,其实就是你 src/main/java 和 src/main/resources 里的东西合并在一起了而已。
结语: 技术没有黑魔法,一切看似复杂的问题,背后往往都是简单的文件操作和路径映射。希望这篇文章能帮你彻底搞懂 Maven 的目录结构,以后的开发之路上少踩几个坑!
更多推荐

所有评论(0)