# 【Maven避坑】源码去哪了?一文看懂 Maven 工程与打包后的目录映射关系

【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 会调用 javacsrc/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.xmlUserMapper.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)

不要只听我说,建议你自己动手验证一下,印象会更深:

  1. 找一个 Maven 项目,执行命令 mvn package
  2. 进入项目的 target 目录。
  3. 找到生成的 .jar 文件。
  4. 把后缀名从 .jar 改成 .zip,然后解压它!

打开解压后的文件夹,你会发现,所谓的"神秘"目录结构,其实就是你 src/main/javasrc/main/resources 里的东西合并在一起了而已。


结语: 技术没有黑魔法,一切看似复杂的问题,背后往往都是简单的文件操作和路径映射。希望这篇文章能帮你彻底搞懂 Maven 的目录结构,以后的开发之路上少踩几个坑!


相关推荐
吴佳浩15 小时前
Python入门指南(六) - 搭建你的第一个YOLO检测API
人工智能·后端·python
踏浪无痕16 小时前
JobFlow已开源:面向业务中台的轻量级分布式调度引擎 — 支持动态分片与延时队列
后端·架构·开源
Pitayafruit16 小时前
Spring AI 进阶之路05:集成 MCP 协议实现工具调用
spring boot·后端·llm
韩立学长16 小时前
【开题答辩实录分享】以《自助游网站的设计与实现》为例进行选题答辩实录分享
java·mysql·spring
ss27316 小时前
线程池:任务队列、工作线程与生命周期管理
java·后端
不像程序员的程序媛17 小时前
Spring的cacheEvict
java·后端·spring
SAP小崔说事儿17 小时前
在数据库中将字符串拆分成表单(SQL和HANA版本)
java·数据库·sql·sap·hana·字符串拆分·无锡sap
凌云若寒17 小时前
半导体代加工企业标签模板痛点的全景式解决方案
java
踏浪无痕17 小时前
JobFlow 实战:无锁调度是怎么做到的
后端·面试·架构
shoubepatien17 小时前
JAVA -- 11
java·后端·intellij-idea