工作中的那些不得意---Maven生命周期以及插件详解
程序员文章站
2022-07-03 18:53:48
...
今天写的比较多,有时间在整理格式,这格式在logdown排版还行。ITeye没去重排,有兴趣可以去看看我的Logdownhttp://yuezaixz.logdown.com/posts/165674-not-proud-of-maven-life-cycle-as-well-as-those-in-the-plugin-details。
最近甚是苦恼,出入项目管理,就遇到如此大的问题:进度紧、资源不足、职能型组织跨部门难协调、产品需求和设计阶段(我也是在需求和设计后才接受该项目)不足等,但这些都是环境的问题,管理这些问题我觉得都是有价值有意义的,我觉得最大的问题还在于人,这些人又包括下面的人和上面的人。
[size=20px;]团队成员的工作方式让我觉得成天在做无用功[/size]
功能实现有漏洞这些都是正常的事情,问题是这问题完全无法用,为什么做完不点一点,自己测试下?如果这还算没那么离谱,那界面上一片混乱,完全没有按照美工的静态页面去实现,界面总是所见即所得的吧,那我只能理解这个人做事遇到问题选择性忽视,做完功能不愿意自测也是因为怕遇到问题的掩耳盗铃行为。
还有就是经常多次询问是否已经提交代码要开始构建项目后,发现还有代码未提交。再然后数据库脚本的更新包也能混杂一些错误的符号导致脚本无法运行,再再然后,提交的页面经常多一个标签少一个标签的导致IE6下会频频出问题,再再再然后……
总之,就是在不断的引入混乱,增加了我无数时间在检查问题上,而且提出的问题修改后问题会不断地重现,要不就引入新的问题。
还有就是加班问题上,引入如此多的混乱,安排的任务都没完成也不愿意加班。被我强留下来后,竟然趁我吃饭的时候跑路了,这点责任心我完全没法接受了。
我知道团队建设是需要经历震荡期的。技术问题是可以弥补的,但是,心态问题、责任心问题我觉得都不是那么好改正的。
他们或许也有些工作的不开心,因为没有需求和设计,缺少美工支持,计划总在变,这些都会影响工作的积极性。开始我也会烦恼这些,但是后来我觉得这些环境因素都是可以克服的,也是挑战。但我完全没有看到他们在困难面前的改变。而我就会选择放弃午休,甚至午饭后晚饭后都立马工作,并且连续一个月不间歇加班。而实际是,加班总是我一个人。
[size=20px;]领导希望做好,也的确重视,但是却不愿意投入[/size]
我是一个热衷技术的人,如果领导安排本年任务是完成该项目,于是兢兢业业地安排年度计划,定方案,再编码,而领导频繁的因为形势变化,改变工作内容和计划。那我付出一年劳动,也挣了一年薪水,但我的工作真的有价值吗?真的做的开心吗?(PS.入职一年未涨过薪水,原因是公司没有给转正一年的职工涨薪的例子。其实薪水和我两年前是一个水平,只是觉得有价值有挑战才继续做)
-------------------------------------分割线-------------------------------------------
[size=20px;]生命周期[/size]
[size=16px;]何为生命周期[/size]
开发人员每天都项目进行清理、编译、测试以及部署就是项目构建的生命周期。
Maven的生命周期就是为了所有的构建过程进行抽象和同意。
Maven的生命周期是抽象的,相当于设计模式的模板模式。只是定义整体的算法,生命周期中真正的工作还是由插件来完成的。
插件绑定又分为内置绑定和默认绑定。
[size=16px;]三套生命周期[/size]
Maven拥有三套相互独立的生命周期,分别为clean、default、site。
Clean是为了清理项目;
Default是构建项目;
Site是为了建立项目站点。
三套生命周期是相互独立的,例如调用clean生命周期的某个阶段(之后有详细说阶段),不会影响对default生命周期产生任何影响。
[size=16px;]生命周期的阶段[/size]
每个生命周期都包含一些阶段(phase),这些阶段是有顺序的,后面的依赖前面的阶段。以clean生命周期为例,包含的阶段有pre-clean、clean和post-clean。当用户调用clean,则会调用pre-clean和clean阶段。
[size=16px;]生命周期以及阶段罗列[/size]
Clean生命周期一共包含了三个阶段
pre-clean 执行一些需要在clean之前完成的工作
clean 移除所有上一次构建生成的文件
post-clean 执行一些需要在clean之后立刻完成的工作
Default生命周期的各个阶段
绝大多数重要的阶段都在该周期中:
validate
generate-sources
process-sources
generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目的源代码。
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
prepare-package
package 接受编译好的代码,打包成可发布的格式,如 JAR 。
pre-integration-test
integration-test
post-integration-test
verify
install 将包安装至本地仓库,以让其它项目依赖。
deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享。
Site生命周期的各个阶段
pre-site 执行一些需要在生成站点文档之前完成的工作
site 生成项目的站点文档
post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
site-deploy 将生成的站点文档部署到特定的服务器上
参考资料
详细一刻参考Maven 官网中的介绍页面的[Lifecycle Reference](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html).章节部分的内容。
[size=16px;]命令行[/size]
### mvn clean
执行clean周期的clean阶段,实际执行的阶段有clean周期的pre-clean和clean阶段。
### mvn test
调用default生命周期的test阶段。实际执行default生命周期知道test的所有阶段。
### mvn clean install
执行clean生命周期的pre-clean和clean阶段,以及default直到install的所有阶段。
### mvn clean deploy site-deploy
执行clean生命周期的pre-clean和clean阶段,以及default的所有阶段,deploy生命周期的所有阶段。
[size=20px;]插件[/size]
[size=16px;]插件的目标[/size]
插件本身为了复用代码,往往完成了多个任务。例如maven-dependency-plugin插件就能够分析项目依赖、列出依赖树、分析依赖来源、列出所有已解析依赖等等。这些功能里面有很多代码其实是复用的,所以为了复用,他们集成为了一个插件。
因此,每个插件的目标就是一个插件的功能。dependency:analyze的目标就是analyze,功能就是分析依赖。dependency:tree的目标tree的功能就是列出依赖树。
[size=16px;]写法[/size]
dependency:tree是一种通用的写法,冒号前面是插件的前缀,后面是插件的目标。例如还有compile:compile就是maven-compiler-plugin的compile目标。
[size=16px;]插件的绑定[/size]
Maven的生命周期与插件相互绑定,用以完成实际的构建。例如项目编译这一任务就是default生命周期compile阶段做的事情,而maven-compile-plugin插件的compile目标就完成该功能。因此,将他们绑定就能实现项目的编译目标。
插件的绑定在之前1.1章节已经说过了,分为内置绑定和自定义绑定。
[size=16px;]内置绑定[/size]
内置绑定是预设的,不用用户配置。Maven已经为完成构建的主要功能,已经在生命周期的各个阶段上绑定了很多插件。例如clean生命周期的clean阶段就与maven-clean-plugin的clean目标绑定。
有一些比较特殊的,比如default生命周期的package阶段,他默认是有maven-jar-plugin:jar 绑定。
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar
install install:install
deploy deploy:deploy
[size=16px;]参考资料[/size]
具体的内容,也可以在[Setting Up Your Project to Use the Build Lifecycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) 章节中看到。
命令输出
也可以从执行命令时候,看Maven控制台的输出,也可以知道具体阶段执行了那些插件目标。
自定义插件
用户自己通过配置,将插件目标与阶段绑定。具体配置如下代码:
org.codehaus.modellomodello-maven-plugin1.4modello-javaverifyjava
groupIdle、artifactId、version为插件的依赖坐标。
Executions下每个execution子元素都可以用来配置执行一个任务。
例子中配置了一个id为modello-java,配置phase配置绑定在了verify生命周期阶段上,在通过goals中配置的指定目标来执行。
运行mvn verify就能看到执行了插件。
### 查询插件绑定
可以查询自定应绑定的插件的详细信息。
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plug
in:2.1.1 –Ddetail 命令后,显示
source:test-jar-no-fork Description: This goal bundles all the test sources into a jar archive. This goal functions the same as the test-jar goal but does not fork the build, and is suitable for attaching to the build lifecycle. Implementation: org.apache.maven.plugin.source.TestSourceJarNoForkMojo Language: java Bound to phase: package Available parameters: archive The archive configuration to use. See Maven Archiver Reference.
Bound to phase: package表示插件目标默认绑定的生命周期阶段为package。
[size=16px;]插件配置[/size]
命令行插件配置
运行命令时候,加上-D(java自带的参数,其功能是通过命令行设置一个java系统属性),实现了插件参数的配置。
例如,maven-surefire-plugin提供了一个maven.test.skip的参数,当值为true的时候,就会跳过执行测试。于是
D:\workspace\hello-world>mvn install -Dmaven.test.skip=true
就会跳过测试阶段。
控制台输出信息含有一下信息。
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ hello-world ---
[INFO] Tests are skipped.
POM中插件全局配置
不是所有参数都可以从命令行执行,有些参数在项目创建到项目发布也都不会改变,就可以在pom文件中一次性配置。比如java 1.5这个参数。
...
org.apache.maven.plugins
maven-jar-plugin
2.1
1.5 source >
1.5 target >
这样,不管绑定到compile阶段,还是绑定到test阶段,都可以用到该配置,急于java1.5进行编译。
POM中插件任务配置
以下配置可以让Maven在绑定的阶段执行任务。也可以绑定多个execetuion,让Maven在不同的生命周期执行不同的任务。
下例为ant脚本插件,用于执行ant命令,输出正在创建的目录,用于提示信息。
maven-antrun-plugin
echodir
run
verify
false
Build Dir: ${project.build.directory}
注意:inherited: 是否此插件配置将会应用于poms,那些继承于此的项目.
[size=16px;]用命令获取插件描述信息[/size]
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plug
in:2.1.1 命令后,显示插件描述信息。
```
D:\workspace\hello-world>mvn help:describe -Dplugin=org.apache.maven
.plugins:maven-compiler-plugin:2.1
Name: Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sour
project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 2.1
Goal Prefix: compiler
This plugin has 3 goals:
compiler:compile
Description: Compiles application sources
compiler:help
Description: Display help information on maven-compiler-pl
Call
mvn compiler:help -Ddetail=true -Dgoal=
to display parameter details.
compiler:testCompile
Description: Compiles application test sources.
For more information, run 'mvn help:describe [...] -Ddetail'
```
描述了插件的坐标、目标。还可以通过最后加-Ddetail参数来获取更多的信息。
[size=16px;]命令行调用插件[/size]
例如mvn dependency:tree 。
[size=16px;]插件解析机制[/size]
插件仓库
我们使用Maven插件的目标的时候都是利用他的前缀(简写),一旦执行命令出问题了,比较难定位具体是哪个插件运行出错的。在此咱们一起来看看它的插件插件机制。为何将仓库的依赖解析和插件解析放在一起呢,因为他们确实有相似的地方。插件的组件也是基于坐标存在于Maven库中,需要的时候,从本地仓库需要相关插件,不存在,从远程仓库去找,找到后下载到本地。
```
•
•
• central
• Maven plugin
• htpp://repo1.maven.org/maven2
• default
•
• true
•
•
• false
•
•
•
```
### 插件默认的groupId
插件配置可以省略groupId,默认为Maven的官方插件。
例如
maven-antrun-plugin
echodir
run
verify
false
Build Dir: ${project.build.directory}
解析插件版本
版本也可以省略,默认会去核心POM中先查看版本,如果不存在就会去*仓库查看maven-metadata.xml,找到插件的最近发布版本来解析。
[size=16px;]插件的前缀[/size]
会去查插件库元数据,里面有插件的前缀(prefix标签下)。
如果各个插件的groupid下的元数据配置文件都不含有前缀,则会报错。
[size=20px;]总结[/size]
主要内容为生命周期和插件,其中对于插件的前缀的查询,还需要进一步理解下。