maven的理想:像一种什么设计模式?—模板方法模式
- 自动走完标准的构建流程:清理 --> 编译 --> 測试 --> 报告 --> 打包 --> 部署
- 统一入口,所有配置在一个pom里搞定
1.maven生命周期、阶段
maven有三个完全独立的生命周期(LifeCycle):Clean,Build,Site。每个生命周期都由一系列阶段(Phase)组成,执行其中某个阶段时,必须将当前周期的所有阶段执行完。LifeCycle和Phase具体的对应关系如下图:
各个生命周期的阶段(phase)定义如下:
阶段 | 处理 | 描述 |
验证 validate | 验证项目 | 验证项目是否正确且所有必须信息是可用的 |
编译 compile | 执行编译 | 源代码编译在此阶段完成 |
测试 Test | 测试 | 使用适当的单元测试框架(例如JUnit)运行测试。 |
包装 package | 打包 | 创建JAR/WAR包如在 pom.xml 中定义提及的包 |
检查 verify | 检查 | 对集成测试的结果进行检查,以保证质量达标 |
安装 install | 安装 | 安装打包的项目到本地仓库,以供其他项目使用 |
部署 deploy | 部署 | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程 |
运行任何一个阶段,都会从其所在生命周期的第一个阶段开始,顺序执行到指定的阶段。比如,mvn package — 本义:执行default周期的package阶段,maven会自动从process-resources阶段开始运行到package阶段结束
maven的构建生命周期,只是一个抽象规范流程。周期内的每个阶段的执行,是交由plugin插件来完成
2.maven插件
插件plugin是绑定到生命周期,承担实际功能的组件。mvn运行时,自动关联插件来运行。下表是maven默认的各阶段对应的插件列表:
生命周期 | 生命周期阶段 | 插件目标 | 执行任务 |
clean | pre-clean | ||
clean | maven-clean-plugin:clean | 删除项目的输出目录 | |
post-clean | |||
site | pre-site | ||
site | maven-site-plugin:site | ||
post-site | |||
site-deploy | maven-site-plugin:deploy | ||
default | process-resources | maven-resources-plugin:resources | 复制主资源文件至主输出目录 |
compile | maven-compiler-plugin:compile | 编译主代码至主输出目录 | |
process-test-resources | maven-resources-plugin:testResources | 复制测试资源文件至测试输出目 | |
test-compile | maven-compiler-plugin:testCompile | 编译测试代码至测试输出目录 | |
test | maven-surefire-plugin:test | 执行测试用例 | |
package | maven-jar-plugin:jar(ejb:ejb jar:jar rar:rar war:war) | 创建项目jar包 | |
install | maven-install-plugin:install | 将项目输出构件安装到本地仓库 | |
deploy | maven-deploy-plugin:deploy | 将项目输出构件部署到远程仓库 |
另外,maven还可以自定义插件,来扩展maven的功能。
问题一:这些插件在哪里设置?
关于插件的配置一般是在pom文件的<plgin>
标签中,具体关系是:<bulid>:<pluginManagement>:<plugins>:<plugin>
。下图是关于maven默认插件和自定义插件的配置示例:
可以看到,默认插件是maven开头,没有execution这一项,不需要再手动绑定声明周期阶段。
问题二:如何执行maven中的这些插件?
Maven 只是定义了抽象的生命周期,生命周期阶段具体执行的操作是由其绑定的插件目标实现的。
PS:LifeCycle、Phase、Plugin、Goal关系?
- 一个 LifeCycle 包含多个 Phase
- 一个 Plugin 可以提供一个/多个 goal
=> 一个 Phase 由一个/多个 goal 实现
也就是说插件目标有一下两种方式被执行:
1)通过绑定到生命周期阶段,而在生命周期阶段执行时被自动调用
命令格式:mvn phase
。比如下面这些常用命令:
-
mvn clean
:清理旧的jar包 -
mvn compile
:编译主程序 -
mvn package
:打包当前项目 -
mvn install
:安装jar到本地库,等于package+放到本地仓库
PS:一个生命周期阶段绑定多个插件目标的情况,其执行顺序是按照POM文件中插件目标定义的顺序。
2)通过直接调用的方式(也就是“plugin:goal”的方式)在生命周期阶段外执行
命令格式:mvn plugin:goal
。比如:
mvn jetty:run
-
mvn com.xupt.yzh:my_maven_plugin:1.0-SNAPSHOT:log
(下面的自定义插件示例)
另外,在执行命令时还可以传入参数,mvn com.xupt.yzh:my_maven_plugin:1.0-SNAPSHOT:log -D log.name=Lisi
PS:直接执行 goal 与执行 phase 的区别是,执行 phase 必须把当前 lifecycle 内之前 phase 也执行,而执行 goal 的话可以只执行当前 goal。
idea 和 eclipse 生成项目最终也是依赖 maven 插件生成的,它们一般自带了默认插件,在 idea 右侧的 maven#plugin 可以看见。一般情况下,我们通过 maven#LifeCycle 直接运行即可。
问题三:如何自定义插件?
插件的开发步骤如下:
1.引入maven api的依赖,设置打包方式为maven-plugin
2. 编写简单Mojo类—继承AbstractMojo,并指定goal,然后打包插件。
注:这里其实也可以直接在 @Mojo 中通过 defaultPhase 指定当前 goal 所属的 phase,比如 defaultPhase = LifecyclePhase.PACKAGE
- 通过命令执行插件
mvn [plugin-name] [goal-name]
,在这里是`
这里再提一点,一个插件可以绑定多个周期。
问题四:自定义插件可以传入参数吗?
可以的,可以通过@Parameter定义参数,并指定默认值
执行结果如下:
现在我在执行命令时通过 -D 传入参数。mvn com.xupt.yzh:my_maven_plugin:1.0-SNAPSHOT:log -D log.name=Lisi
,执行结果如下:
虽然我们可以自定义插件,但在实际开发中,使用默认插件就完全够用了,自定义插件很少用到。