mvn clean
本章是"常用命令"系列的开篇。理解
mvn clean的作用和 clean 生命周期,是掌握 Maven 构建"可复现性"的第一步——每次构建都从干净状态开始,避免旧产物干扰新结果。
核心机制
Clean 生命周期用于清理项目的工作目录,删除上一次构建生成的所有文件。它由 pre-clean、clean、post-clean 三个阶段组成,其中 clean 阶段是核心,负责删除 target/ 目录。
clean 生命周期包含哪些阶段?
| 阶段 | 作用 | 默认绑定的插件目标 |
|---|---|---|
pre-clean | 执行清理前的预处理 | 无默认绑定 |
clean | 删除 target/ 目录 | maven-clean-plugin:clean |
post-clean | 执行清理后的收尾工作 | 无默认绑定 |
日常使用中,执行 mvn clean 实际上只运行了 pre-clean 和 clean 两个阶段(post-clean 通常无操作)。
clean 到底删除了什么?
maven-clean-plugin 的默认行为是删除项目根目录下的 target/ 目录。target/ 目录中通常包含:
- 编译后的
.class文件(target/classes/) - 测试编译产物(
target/test-classes/) - 打包产物(
target/*.jar或target/*.war) - 测试报告(
target/surefire-reports/) - 生成的文档(
target/site/) - 临时文件和缓存
注意:mvn clean 只删除构建产物,绝不删除 src/ 目录下的源代码和资源文件。
为什么需要 clean?
想象你(后端小崔)昨天编译了项目,今天修改了一个类的包名后重新编译。如果没有 clean,旧的 .class 文件可能仍然留在 target/classes/ 的旧路径下,导致运行时类加载器同时加载新旧两个路径的类,产生难以排查的 NoClassDefFoundError 或重复类问题。
clean 的价值在于:确保每次构建都是"从零开始",消除历史产物的干扰。
生活类比:厨房备菜
想象厨师(Maven)要做一道菜(构建项目):
- 不 clean 直接构建:厨师在已经用过的砧板上直接切新食材,砧板上还残留着昨天切过的蒜末和辣椒碎。新菜可能串味,顾客(运行时)吃到奇怪的味道(类冲突、旧资源干扰)。
- 先 clean 再构建:厨师每次开工前先把砧板、刀具、锅具全部清洗一遍(删除
target/),然后从干净的台面开始备菜。每道菜的味道都是纯粹、可预期的。
图示
上图展示了 mvn clean 的核心行为:执行前 target/ 目录包含各类构建产物;执行后整个 target/ 目录被删除,项目回到"源码-only"的干净状态。
完整示例
场景
飞翔科技的 employee-system 项目已经经过多次构建,CTO 大翔要求小崔在提交代码前必须执行一次干净构建,确保没有旧产物干扰。
操作前:项目状态
经过多次构建后,target/ 目录内容如下:
employee-system/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ └── test/
│ ├── java/
│ └── resources/
└── target/ ← 构建产物目录
├── classes/ ← 编译后的 .class 文件
│ └── com/feixiang/...
├── test-classes/ ← 测试编译产物
├── employee-system-1.0.0.jar ← 上次打包的 JAR
├── employee-system-1.0.0.jar.original
├── maven-archiver/
├── surefire-reports/ ← 测试报告
│ ├── TEST-com.feixiang.EmployeeServiceTest.xml
│ └── com.feixiang.EmployeeServiceTest.txt
└── generated-sources/ ← 代码生成产物
操作步骤
步骤一:执行 clean
mvn clean
步骤二:观察输出
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< com.feixiang:employee-system >------------------
[INFO] Building employee-system 1.0.0
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ employee-system ---
[INFO] Deleting C:\Users\xiaocui\workspace\employee-system\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.523 s
[INFO] Finished at: 2024-01-15T10:30:00+08:00
[INFO] ------------------------------------------------------------------------
关键输出解读:
clean:3.2.0:clean—— 执行的是maven-clean-plugin版本 3.2.0 的clean目标Deleting ...\target—— 插件正在删除target/目录BUILD SUCCESS—— 清理成功(clean 本身不会编译或测试,所以只要目录删除成功就算成功)
步骤三:验证清理结果
ls target/
输出:
ls: cannot access 'target/': No such file or directory
target/ 目录已完全消失,项目回到干净状态。
clean 与 clean package 组合
在实际工作中,clean 很少单独使用,通常与 package 组合:
mvn clean package
这个命令的执行顺序是:
- 先执行 clean 生命周期:删除
target/ - 再执行 default 生命周期:从
validate到package,重新编译、测试、打包
组合前后的产物对比:
| 对比项 | mvn package(不 clean) | mvn clean package(推荐) |
|---|---|---|
| 编译产物 | 增量编译,旧 .class 可能残留 | 全新编译,无旧文件残留 |
| 打包产物 | 新 JAR 覆盖旧 JAR | 全新生成的 JAR |
| 测试报告 | 追加或覆盖 | 全新生成 |
| 可复现性 | 可能受历史状态影响 | 每次结果一致 |
飞翔科技的 Jenkins 流水线中,李眉配置的构建命令统一为:
mvn clean package -P${ENV}
其中 ${ENV} 由 Jenkins 环境变量注入(dev/test/prod)。
易错点与常见问题
误区一:clean 会删除源代码
错误认知:"mvn clean 把 target/ 删了,会不会把 src/ 也删了?"
纠正:maven-clean-plugin 的默认配置只删除 target/ 目录,绝不触碰 src/。插件的配置在 pom.xml 中可见:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<filesets>
<fileset>
<directory>target</directory>
</fileset>
</filesets>
</configuration>
</plugin>
如果你自定义了 <directory>src</directory>,那才会删除源码——但这是反模式,不要这么做。
误区二:clean 失败会影响后续构建
典型问题:小崔执行 mvn clean package 时,clean 阶段报错 Permission denied,但 package 阶段仍然执行了。
纠正:mvn clean package 是一个连续命令,如果 clean 阶段失败(如文件被占用、权限不足),Maven 默认会停止整个构建,不会继续执行 package。如果你看到 package 继续执行,说明 clean 实际上成功了,或者你执行的是 mvn clean; mvn package(分号分隔的两个独立命令)。
误区三:clean 可以跳过
错误认知:"我昨天才构建过,代码没改,今天直接 mvn package 就行,不用 clean,省时间。"
纠正:在以下场景下,不 clean 直接构建是危险的:
- 删除了一个 Java 类,但旧
.class仍留在target/classes/ - 修改了资源文件,但旧资源被缓存
- 切换了 Git 分支,两个分支的源码结构不同
- 修改了
pom.xml中的依赖版本
最佳实践:在 CI/CD 环境、发布构建、提交代码前的本地验证中,始终使用 mvn clean package。只有日常开发中的快速编译(mvn compile)可以省略 clean。
小结
mvn clean 是 Maven 构建的"重置按钮",它通过 clean 生命周期删除 target/ 目录,确保后续构建不受历史产物干扰。核心要点:
- clean 生命周期包含
pre-clean、clean、post-clean三个阶段 - 实际删除工作由
maven-clean-plugin完成,默认只删target/ - 生产环境始终使用
mvn clean package,保证构建可复现 - 不 clean 直接构建在特定场景下可以节省时间,但存在旧产物干扰的风险
本章与全局的关系:本章讲解了清理命令。下一章 mvn compile 将带你进入 default 生命周期的第一个核心阶段——编译。