第三章
3.3 编译测试代码
dependency节点下可以声明依赖范围,默认是compile,如果声明为test,则只在测试范围下有效。
3.4 打包
maven默认打包成jar包,通过jar:jar命令.
直接打包的jar包,是不能直接运行的。为了生成可执行的jar文件,需要借助maven-shade-plugin。
3.5 archetype生成项目骨架
可以使用archetype插件快速实现特定的项目骨架
第五章
5.2 maven坐标
maven中的任何构件都必须有自己的坐标,而一组maven坐标是通过一组元素定义的,groupid,artifactid,version,packing,classifier。
groupid:精确到公司中的某个项目
artifactid:项目中的某个模块
version:版本
packing:打包方式
classifier:帮助定义一些附属构件,比如某个jar包的jardoc,和source的jar包。
项目构建的文件名也是跟坐标有关的,一般是artifactid-version.packing。因此artifactid元素一般要带上整个项目的名字。这样当多个项目有相同的模块名时,就不会混淆。
5.4 依赖配置
dependency节点下,配置依赖的项目。每个依赖可以包含以下元素。
groupid,artifactid,version是必须包含的
type:对应于坐标的packing,默认是jar。
scope:依赖范围。
optional:是否可选
exclusions:排除依赖的可传递性
5.5 依赖范围
依赖范围是用来控制依赖与classpath(编译classpath,测试classpath,运行classpath)的关系。
compile:编译依赖范围,默认的。
test:测试依赖范围。
provided:在编译和测试下有效,但是运行classpath下无效。典型的例子是servlet-api,编译和测试的时候需要。运行的时候,由于web容器已经提供了,所以就不需要重复的引用了。
runtime:运行时依赖。测试和运行时有效,编译时无效。典型的例子是jdbc驱动。
system:和provided的依赖范围完全相同。不过,依赖的元素是通过systemPath指定的,跟本机系统有关,可能造成构建的不可移植性。
import:导入依赖范围。不会对 三种classpath产生任何实际的影响。
5.6 传递性依赖
A依赖B,B依赖C,那么A也会间接的依赖C。Maven回解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式,引入到当前项目中。
上面的情况中,A是B的第一直接依赖,B是C的第二直接依赖。
传递性依赖和依赖范围如下表所示。
最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格表示传递依赖范围。
5.7 依赖调解
比如A->B->C->X(1.0),A->D->X(2.0)。X是传递性依赖,并且两条不同的路径都引用了。如果两个版本都被解析,显然是不对的,造成了重复引用。maven的第一个原则是:路径最短者优先。当两条路径的长度一样是,第一声明优先。即POM依赖声明的顺序,决定了引入的版本。如果B在D之前声明,那么就引入1.0版本。
5.8 可选依赖
A->B,B->X(可选),B->Y(可选)。可选依赖不会传递,所以X和Y不会对A产生影响。可选依赖一般都是用于实现不同的特性。在理想的情况下,是不应该使用可选依赖的。
5.9 最佳实践
依赖管理是maven的核心,下面介绍maven管理依赖的常用技巧。
排除依赖
如果当前项目引用了一个第三方依赖,这个第三方依赖又依赖了另一个项目的不稳定版本,可能需要把这个不稳定依赖排除掉。dependency节点下的exclusions节点就可以配置。
有时候想替换掉某个传递性依赖。
归类依赖
比如spring项目里面,有很多依赖的版本号都相同。可以把依赖的版本定义在properties里面,然后引用的时候通过这些属性去应用。这样升级版本就比较方便。
优化依赖
maven会解析项目中所有的直接依赖和传递依赖,并且根据规则,判断每个包的范围,以确保一个依赖只有唯一的版本在项目中存在。
mvn dependency:list 可以查看当前项目已解析的所有依赖。
mvn dependency:tree 查看当前项目的依赖树。
mvn dependency:analyze 可以帮助我们分析当前项目的依赖。
第六章 仓库
maven仓库分为本地仓库和远程仓库,远程仓库又可以是maven中心仓库,局域网搭建的代理私服,或者是其他的公共仓库。
只有当构件被下载到本地仓库后,才能被使用。当本地仓库没有相应的构件时,就回去远程仓库下载。
由于初始时,本地仓库是空的,必须配置一个远程仓库。中央仓库就是默认的远程仓库。
可以配置自己的远程仓库,通过pom文件的 repository配置。如果仓库需要认证消息,则可以在本机的settings文件里配置,通过servers节点进行配置用户名和密码。
6.4 部署到远程仓库
maven项目还可以部署到远程仓库,供别人使用。通过pom文件的distributionManagement节点配置远程仓库。配置正确后,可以通过 mvn clean deploy部署。
6.5 快照版本
maven会自动从仓库中检索最新的快照版本。稳定版本如果在本地仓库存在,就不会去远程仓库检索。快照版本只应该在组织内部使用,而不应该依赖外部的快照。
6.7 镜像
如果仓库X可以提供仓库Y的所有内容,称X是Y的镜像。在settings.xml文件通过mirrors节点配置,mirrorOf配置被代理的镜像,任何对被代理镜像的访问,都会转发至该镜像。
镜像的一个用途是结合私服,代理所有的外部公共仓库。一个私服地址,就等于所有的外部仓库。镜像仓库完全屏蔽了被镜像仓库,当镜像仓库停止服务时,将不能访问被镜像仓库。
第七章 生命周期和插件
maven的生命周期是抽象的,通过绑定插件来实现。
maven有三套相互独立的生命周期,他们分别是clean,default,site。
clean生命周期是清理项目。default是构建项目。site是建立项目站点。
每套生命周期包含一些阶段,并且这些阶段是有顺序的,后面的生命周期依赖于前面的。
三套生命周期本身是独立的。mvn compile命令并不会自动触发clean生命周期。
clean生命周期
1)pre-clean
2)clean
3)post-clean
当调用pre-clean时,只会执行pre-clean阶段,当调用clean时,会执行pre-clean和clean阶段。
default生命周期
default定义了构建项目需要执行的所有步骤。主要包括以下阶段:
validate,initialize,generate-sources,process-sources处理项目主资源文件。
generate-resources,process-resources
compile编译项目主代码
process-classes,generate-test-sources.......test-compile
test,pre-package,package,integration-test,verify
install,deploy
site生命周期
site生命周期是建立和发布项目站点。
pre-site
site
post-site
site-deploy将项目发布到服务器上。
常用maven命令
mvn clean install 从clean生命周期,到default生命周期的install阶段
mvn clean test 从clean生命周期到default生命周期的test阶段。
7.3 插件目标
插件的一个功能就是插件目标。比如maven-dependency-plugin可以分析项目依赖,打印依赖树等。
上面的每一个功能就对应一个目标。dependency:list,dependency:tree,冒号后面就是插件目标。冒号前面是插件名称。
maven生命周期的不同阶段通过绑定不同插件的目标来实现。
7.5 插件配置
用户可以在maven命令中通过-D给插件目标传递参数。用户可以在pom中对插件进行配置,并绑定到一个maven的生命周期上。在build节点的plugin节点下配置。
7.7 从命令行调用插件
maven支持直接从命令行调用插件目标,因为有些插件目标不需要绑定在生命周期上。比如dependency:tree。
7.8 插件解析机制
插件存储在插件仓库中,插件仓库通过pluginRepositories配置。
dependency是插件的别名,maven会自动解析出groupid,artifactid和version。但是建议使用插件的时候,显示的指定版本和groupid。
第八章 聚合和继承
8.2 聚合
开发实际项目的过程中,可能需要把项目分成不同的模块。如果每个模块都分别构建,就会显得很麻烦。
maven的聚合特性,能够把不同的模块一起构建,简化pom的同时,还能保证模块配置的一致性。
聚合模块本身作为一个maven项目,需要有自己的pom文件。其中packing的值为pom。用户可通过一个打包方式为pom的maven项目中声明
任意数量的module元素来实现模块的聚合。module的值是相对于当前聚合项目的相对路径。
聚合模块仅有pom.xml,没有主代码和测试代码目录。
8.3 继承
可以把多个子项目中重复的groupid,依赖,构建插件等抽取到一个父类模块中。作为父模块的项目也只有一个pom文件,打包方式也是pom。
子模块继承的时候通过parent节点指定父模块,通过relativePath指定父模块的相对路径。子模块应该显示的生命自己的artifactid,groupid和version可以
从父模块继承。
可继承的pom元素有很多:groupid,version,artifactid,dependencies,build,dependencyManagement等。
maven提供的dependencyManagement元素既能让子模块继承父模块的配置,又能让子模块保持灵活性。
在父模块中使用dependencyManagement元素配置依赖,配置groupid,artifactid,version。然后在子模块中引入dependency再次引入所需的依赖,
但是只需配置groupid和artifactid,不用配置version。这样就不会发生多个子模块依赖版本不一致的情况。如果没有在子模块再次引入依赖,那么父模块
配置的依赖,不会有任何效果。
通过import依赖范围配置,可以将一个POM文件的dependencyManagement配置引入到当前pom中。
pluginManagement元素可以配置build插件的依赖,功能类似于dependencyManagement。
8.4 聚合和继承的关系
对于聚合模块来说,它知道有哪些被聚合的模块,但是被聚合的模块不知道聚合模块的存在。
对于继承来说,父模块不知道子模块的存在,子模块必须可以找到父模块。
在实际项目中,往往会发现一个pom既是聚合pom又是父pom。这样做比较方便。
8.6 反应堆
反应堆就是根据模块之间的聚合和继承关系,计算出来的模块构建顺序。构建子模块时,必须先构建父模块。
如果用户不想构建整个项目,只想构建某个模块,可以通过一些参数,裁剪反应堆。
-am -pl -amd -rf
第九章 使用nexus创建私服
通过nexus可以代理中央仓库,第三方仓库,还可以创建自己的仓库,供组织内部使用。可以为不同的项目创建不同的仓库,
防止项目冲突。
nexus支持权限管理,支持索引依赖和构件。
第十章 使用maven进行测试
测试覆盖率报告,cobertura是一个优秀开源的代码覆盖率统计工具,maven通过covertura-maven-plugin与之集成。用于通过以下
命令就可以生成测试报告,mvn cobertura:cobertura。