【Maven实战】笔记

Maven配置

setting.xml

位置

  • M2_HOME/conf/setting.xml为全局配置

  • 用户/.m2/setting.xml为用户范围配置

设置HTTP代理 proxies

配置仓库认证信息 servers

profiles 不同情况下的配置

mirrors 配置镜像

pom.xml

头部project

声明了一些POM相关的命名空间及xsd元素,虽然这些属性不是必须的,但使用这些属性能够让第三方工具帮助我们快速编辑POM

repositories

  • 可以使用repository子元素声明一个或者多个远程仓库

  • releases的enabled值为true表示开启发布版本的下载支持

  • snapshots的enabled值为true表示开启快照版本的下载支持

  • updatePolicy用来配置Maven从远程仓库检查更新的频率

  • checksumPolicy用来配置Maven检查检验和文件的策略

项目打包后能部署到远程仓库 distributionManagement

packaging 打包方式

finalName 生成包的时候最终的名字定义

命令

mvn clean compile

clean 清理输出目录target/

compile 编译主代码到target/

mvn clean test

会先执行编译

test 默认的测试代码目录是src/test/java

mvn clean package

会先执行编译、测试

package 把主代码打包成xxx-SNAPSHOT.jar并输出到target/

mvn clean install

会先执行编译、测试、打包

install 将项目输出的jar安装到了Maven本地仓库中

想要生成可运行的jar,需要配置插件maven-shade-plugin,生成两个jar,一个为原始的。打开另一个的META-INF/MAINFEST.MF

坐标和依赖

传递性依赖

有了传递性依赖,maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中

依赖调解

若两条依赖路径上有两个版本的X,第一原则是:路径最近者优先

解析依赖树

mvn dependency:list

mvn dependency:tree

mvn dependency:analyze

仓库

快照版本 SNAPSHOT

当把项目设置成快照版本,推到仓库后,若有项目依赖该版本,maven会自动从仓库中检查快照版本项目的最新版本,并更新下载,因此具有不稳定性。用户也可以使用命令行-U参数强制让Maven检查更新:mvn clean install -U

最新发布版本 RELEASE

最新版本(包括快照) LATEST

镜像

如果仓库A可以提供仓库B的所有内容,那么A为B的一个镜像。

mirrorOf

mirrorOf的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像,一般会结合私服使用。

1
2
3
4
<mirrorOf>*</mirrorOf>
<mirrorOf>external:*</mirrorOf>
<mirrorOf>repo1,repo2</mirrorOf>
<mirrorOf>*,!repo1</mirrorOf>

生命周期和插件

Maven拥有三套相互独立的生命周期,它们分别是clean、default和site

  • clean生命周期的目的是清理项目

  • default生命周期的目的是构建项目

  • site生命周期的目的是建立项目站点

每个生命周期包含一些阶段

clean 生命周期

clean生命周期的目的是清理项目,它包含三个阶段(phase):

pre-clean:执行一些清理前需要完成的工作
clean:清理上一次构建生成的文件
post-clean:执行一些清理后需要完成的工作

default 生命周期

validate
initialize
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 打包编译好的代码
pre-integration-test
integration-test
post-instregration-test
verify
install 将包安装到Maven本地仓库
deploy 将最终的包复制到远程仓库

sit 生命周期

pre-site 执行生成站点之前要完成的工作
site 生成项目站点文档
post-site 执行生成站点之后要完成的工作
site-deploy 将生成的项目站点发布到服务器上

命令行与生命周期

mvn clean install命令实际调用了clean生命周期的pre-clean、clean阶段,以及default生命周期的从validate至install所有阶段。

插件目标

对于插件本身,为了能够复用代码,它往往能够完成多个任务,这些功能聚集在一个插件里,每个功能就是一个插件目标。通用写法:冒号前面是插件前缀,冒号后面是插件目标(dependency:analyze)

插件绑定

Maven的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互绑定

插件配置:命令行配置

用户可以在Maven命令中使用-D参数,并伴随一个参数键=参数值的形式,来配置插件目标的参数。例如,在运行命令的时候,加上如下-D参数就能跳过测试

1
mvn install -Dmaven.test.skip=true

参数-D时Jave自带的,其功能是通过命令行设置一个Java系统属性,Maven简单地重用了该参数

获取插件信息

基本上所有主要的Maven插件都来自于Apache和Codehaus

插件目标前缀

为了更简洁,Maven引入了目标前缀的概念,help是maven-help-plugin的目标前缀,dependency是maven-dependency-plugin的前缀。

插件解析机制

与依赖构件一样,插件构件同样基于坐标存储在Maven仓库中,插件的远程仓库使用pluginRepositories和pluginRepository配置

Maven在超级POM中为所有核心插件设定了版本

Maven在解析插件仓库元数据的时候,会默认使用org.apache.maven.plugins和org.codehaus.mojo两个groupId,也可以通过配置setting.xml让Maven检查其他groupId上的插件仓库元数据

1
当Maven解析到dependency:tree这样的命令后,它首先基于默认的groupId归并所有插件仓库的元数据maven-metadata.xml;其次检查归并后的元数据,找到对应的artifactId为maven-dependency-plugin;然后结合当前元数据的groupId:org.apache.maven.plugin;最后解析得到完整的插件坐标。

聚合与继承

聚合:主要是为了方便快速构建项目

Maven的聚合特性能够把项目的各个模块聚合在一起构建

两个子模块外面包着一个父模块,父模块也作为一个Maven项目,因此也有POM

1
2
3
4
5
6
7
...
<packaging>pom</packaging>
...
<modules>
<module>xx1</module>
<module>xx2</module>
</modules>

注意:聚合模块和其他模块的目录结构并非一定是父子结构,若是平行结构,聚合POM中module的路径也要做相应修改

继承:主要是为了消除重复配置

Maven的继承特性则能帮助抽取各模块相同的依赖和插件等配置

父模块使用了与其他模块一致的groupId和version,打包方式也要为pom

1
2
3
...
<packaging>pom</packaging>
...

子模块继承父模块

1
2
3
4
5
6
7
8
...
<parent>
<groupId>xx</groupId>
<artifactId>xx-parent</artifactId>
<version>xx</version>
<relativePath>../pom.xml</relativePath>
</parent>
...

反应堆:在一个多模块的Maven项目中,反应堆是指所有模块组成的一个构建结构

实际的构建顺序是这样形成的:Maven按序读取POM,如果该POM没有依赖模块,那么就构建该模块,否则就先构建其依赖模块,如果该依赖还依赖其他模块,则进一步先构建依赖的依赖

测试

mvn test:test阶段与maven-surefire-plugin的test目标绑定

扫描src/test/java/下符合命名模式的测试类

  • */Test.java

  • */Test.java

  • */TestCase.java

mvn package-DskipTests:跳过测试

mvn test -Dtest = xxxTest:只运行某个测试类,可以用逗号分隔

使用Maven构建Web应用

使用jetty-maven-plugin进行测试(热部署)

能够周期性地检查项目内容,发现变更后自动更新到内置的Jatty Web容器中,使用很简单,配置jetty-maven-plugin插件

1
2
3
4
5
6
7
8
9
10
11
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>xx</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webAppConfig>
<contextPath>/test</contextPath>
</webAppConfig>
</configuration>
</plugin>

scanIntervalSeconds是扫描项目变更的时间间隔,默认为0,表示不扫描,因此需要配置时间才会自动化热部署。为了能在命令行直接运行mvn jetty:run,用户需要配置setting.xml:

1
2
3
4
5
<setting>
<pluginGroups>
<pluginGroup>org.mortbay.jetty</pluginGroup>
</pluginGroups>
</setting>

版本管理:<主版本>.<次版本>.<增量版本>-<里程碑版本>

灵活的构建

Maven为了支持构建的灵活性,内置了三大特性,即属性、Profile、资源过滤

属性

通过元素用户可以自定义一个或多个Maven属性,然后在POM的其他地方使用${属性名称}的方式引用属性。

  • 内置属性:${basedir}根目录、${version}项目版本

  • POM属性:例如 ${project.artifactId}

  • 自定义属性:

  • Settings属性:例如 ${settings.localRepository}

  • Java系统属性:例如 ${user.home}

  • 环境变量属性:例如 ${env.JAVA_HOME}

资源过滤

将数据放到下,通过命令激活数据。要为资源目录开启过滤,只要在此基础上添加一行filtering配置即可

1
2
3
4
5
6
7
8
<profiles>
<profile>
<id>dev</id>
<properties>
<db.driver>xxx</db.driver>
</properties>
</profile>
</profiles>

Maven Profile

profile能够在构建的时候修改POM的一个子集,或者添加额外的配置元素。用户可以使用很多方式激活profile,以实现构建在不同环境下的移植。

激活profile

  • 命令行激活:mvn clean install -Pdev

  • settings文件显示激活

1
2
3
4
5
<setting>
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
</setting>
  • 系统属性激活
1
2
3
4
5
6
7
8
9
<profiles>
<profile>
<activation>
<property>
<name>test</name>
</property>
</activationid>
</profile>
</profiles>

可以在命令行声明系统属性
mvn clean install -Dtest = x

  • 操作系统环境
1
2
3
4
5
6
7
8
9
10
<profiles>
<profile>
<activation>
<os>
<name>Windows XP</name>
···
</os>
</activationid>
</profile>
</profiles>
  • 文件存在与否激活

  • 默认激活

Web资源过滤

在Web项目中,资源文件同样位于src/main/resources/目录下,它们经过处理后会位于WAR包的WEB-INF/classes目录下,这也是Java代码编译打包后的目录。也就是说,这类资源文件在打包过后位于应用程序的classpath中。Web项目中还有另外一类资源文件,默认它们的源码位于src/main/webapp/目录,经打包后位于WAR包的根目录。

编写Maven插件

  • 创建Maven项目,它的packaging为mavn-plugin

  • 编写插件目标,继承AbstractMojo类

  • 为目标配置参数,在编写mojo类时需要注意提供可配置的参数

  • 编写代码实现目标行为,实现mojo的execute()方法

  • 错误处理及日志

  • 测试插件

Archetype

可以Archetype理解为Maven项目的模板

mvn archetype:generate

参考文献

  • 【Maven实战】书籍