# 【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 的目录结构,以后的开发之路上少踩几个坑!


相关推荐
木木一直在哭泣39 分钟前
Java Stream.filter 全面解析:定义、原理与最常见使用场景
后端
绫语宁1 小时前
以防你不知道LLM小技巧!为什么 LLM 不适合多任务推理?
人工智能·后端
v***55341 小时前
springboot使用logback自定义日志
java·spring boot·logback
qq_336313931 小时前
java基础-集合进阶
java·开发语言·windows
稚辉君.MCA_P8_Java1 小时前
Gemini永久会员 归并排序(Merge Sort) 基于分治思想(Divide and Conquer)的高效排序算法
java·linux·算法·spring·排序算法
q***18841 小时前
Spring Boot中的404错误:原因、影响及处理策略
java·spring boot·后端
222you1 小时前
MybatisPlus常用注解
java·开发语言·spring
用户69371750013841 小时前
17.Kotlin 类:类的形态(四):枚举类 (Enum Class)
android·后端·kotlin
h***34631 小时前
MS SQL Server 实战 排查多列之间的值是否重复
android·前端·后端