Maven

Maven 功能

Maven 能够帮助开发者完成以下工作:

  • 构建
  • 文档生成
  • 报告
  • 依赖
  • SCMs
  • 发布
  • 分发
  • 邮件列表

约定配置

Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。如下所示:

目录 目的
${basedir} 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources 项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${basedir}/target/classes 编译输出目录
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository Maven默认的本地仓库目录位置

Maven 特点

  • 项目设置遵循统一的规则。
  • 任意工程中共享。
  • 依赖管理包括自动更新。
  • 一个庞大且不断增长的库。
  • 可扩展,能够轻松编写 Java 或脚本语言的插件。
  • 只需很少或不需要额外配置即可即时访问新功能。
  • 基于模型的构建 − Maven能够将任意数量的项目构建到预定义的输出类型中,如 JAR,WAR 或基于项目元数据的分发,而不需要在大多数情况下执行任何脚本。
  • 项目信息的一致性站点 − 使用与构建过程相同的元数据,Maven 能够生成一个网站或PDF,包括您要添加的任何文档,并添加到关于项目开发状态的标准报告中。
  • 发布管理和发布单独的输出 − Maven 将不需要额外的配置,就可以与源代码管理系统(如 Subversion 或 Git)集成,并可以基于某个标签管理项目的发布。它也可以将其发布到分发位置供其他项目使用。Maven 能够发布单独的输出,如 JAR,包含其他依赖和文档的归档,或者作为源代码发布。
  • 向后兼容性 − 您可以很轻松的从旧版本 Maven 的多个模块移植到 Maven 3 中。
  • 子项目使用父项目依赖时,正常情况子项目应该继承父项目依赖,无需使用版本号,
  • 并行构建 − 编译的速度能普遍提高20 - 50 %。
  • 更好的错误报告 − Maven 改进了错误报告,它为您提供了 Maven wiki 页面的链接,您可以点击链接查看错误的完整描述。

Maven构建生命周期

Maven 构建生命周期定义了一个项目构建跟发布的过程。

一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:

Maven - 图1

阶段 处理 描述
验证 validate 验证项目 验证项目是否正确且所有必须信息是可用的
编译 compile 执行编译 源代码编译在此阶段完成
测试 Test 测试 使用适当的单元测试框架(例如JUnit)运行测试。
包装 package 打包 创建JAR/WAR包如在 pom.xml 中定义提及的包
检查 verify 检查 对集成测试的结果进行检查,以保证质量达标
安装 install 安装 安装打包的项目到本地仓库,以供其他项目使用
部署 deploy 部署 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程

为了完成 default 生命周期,这些阶段(包括其他未在上面罗列的生命周期阶段)将被按顺序地执行。

Maven 有以下三个标准的生命周期:

  • clean:项目清理的处理
  • default(或 build):项目部署的处理
  • site:项目站点文档创建的处理

构建阶段由插件目标构成

一个插件目标代表一个特定的任务(比构建阶段更为精细),这有助于项目的构建和管理。这些目标可能被绑定到多个阶段或者无绑定。不绑定到任何构建阶段的目标可以在构建生命周期之外通过直接调用执行。这些目标的执行顺序取决于调用目标和构建阶段的顺序。

例如,考虑下面的命令:

clean 和 pakage 是构建阶段,dependency:copy-dependencies 是目标

  1. mvn clean dependency:copy-dependencies package

这里的 clean 阶段将会被首先执行,然后 dependency:copy-dependencies 目标会被执行,最终 package 阶段被执行。

Clean 生命周期

当我们执行 mvn post-clean 命令时,Maven 调用 clean 生命周期,它包含以下阶段:

  • pre-clean:执行一些需要在clean之前完成的工作
  • clean:移除所有上一次构建生成的文件
  • post-clean:执行一些需要在clean之后立刻完成的工作

mvn clean 中的 clean 就是上面的 clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,如果执行 mvn clean 将运行以下两个生命周期阶段:

  1. pre-clean, clean

如果我们运行 mvn post-clean ,则运行以下三个生命周期阶段:

  1. pre-clean, clean, post-clean

我们可以通过在上面的 clean 生命周期的任何阶段定义目标来修改这部分的操作行为。

Default (Build) 生命周期

这是 Maven 的主要生命周期,被用于构建应用,包括下面的 23 个阶段:

生命周期阶段 描述
validate(校验) 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。
initialize(初始化) 初始化构建状态,比如设置属性值。
generate-sources(生成源代码) 生成包含在编译阶段中的任何源代码。
process-sources(处理源代码) 处理源代码,比如说,过滤任意值。
generate-resources(生成资源文件) 生成将会包含在项目包中的资源文件。
process-resources (处理资源文件) 复制和处理资源到目标目录,为打包阶段最好准备。
compile(编译) 编译项目的源代码。
process-classes(处理类文件) 处理编译生成的文件,比如说对Java class文件做字节码改善优化。
generate-test-sources(生成测试源代码) 生成包含在编译阶段中的任何测试源代码。
process-test-sources(处理测试源代码) 处理测试源代码,比如说,过滤任意值。
generate-test-resources(生成测试资源文件) 为测试创建资源文件。
process-test-resources(处理测试资源文件) 复制和处理测试资源到目标目录。
test-compile(编译测试源码) 编译测试源代码到测试目标目录.
process-test-classes(处理测试类文件) 处理测试源码编译生成的文件。
test(测试) 使用合适的单元测试框架运行测试(Juint是其中之一)。
prepare-package(准备打包) 在实际打包之前,执行任何的必要的操作为打包做准备。
package(打包) 将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。
pre-integration-test(集成测试前) 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。
integration-test(集成测试) 处理和部署项目到可以运行集成测试环境中。
post-integration-test(集成测试后) 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。
verify (验证) 运行任意的检查来验证项目包有效且达到质量标准。
install(安装) 安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。
deploy(部署) 将最终的项目包复制到远程仓库中与其他开发者和项目共享。

有一些与 Maven 生命周期相关的重要概念需要说明:

当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。

不同的 maven 目标将根据打包的类型(JAR / WAR / EAR),被绑定到不同的 Maven 生命周期阶段。

Site 生命周期

Maven Site 插件一般用来创建新的报告文档、部署站点等。

  • pre-site:执行一些需要在生成站点文档之前完成的工作
  • site:生成项目的站点文档
  • post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
  • site-deploy:将生成的站点文档部署到特定的服务器上

这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。 在下面的例子中,我们将 maven-antrun-plugin:run 目标添加到 Site 生命周期的所有阶段中。这样我们可以显示生命周期的所有文本信息。

Maven 构建配置文件

构建配置文件是一系列的配置项的值,可以用来设置或者覆盖 Maven 构建默认值。

使用构建配置文件,你可以为不同的环境,比如说生产环境(Production)和开发(Development)环境,定制构建方式。

配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。配置文件在构建时修改 POM,并且用来给参数设定不同的目标环境(比如说,开发(Development)、测试(Testing)和生产环境(Production)中数据库服务器的地址)。


构建配置文件的类型

构建配置文件大体上有三种类型:

类型 在哪定义
项目级(Per Project) 定义在项目的POM文件pom.xml中
用户级 (Per User) 定义在Maven的设置xml文件中 (%USER_HOME%/.m2/settings.xml)
全局(Global) 定义在 Maven 全局的设置 xml 文件中 (%M2_HOME%/conf/settings.xml)

配置文件激活

Maven的构建配置文件可以通过多种方式激活。

  • 使用命令控制台输入显式激活。
  • 通过 maven 设置。
  • 基于环境变量(用户或者系统变量)。
  • 操作系统设置(比如说,Windows系列)。
  • 文件的存在或者缺失。

配置文件激活实例

假定项目结构如下:

Maven - 图2

其中在src/main/resources文件夹下有三个用于测试文件:

文件名 描述
env.properties 如果未指定配置文件时默认使用的配置。
env.test.properties 当测试配置文件使用时的测试配置。
env.prod.properties 当生产配置文件使用时的生产配置。

注意:这三个配置文件并不是代表构建配置文件的功能,而是用于本次测试的目的;比如,我指定了构建配置文件为 prod 时,项目就使用 env.prod.properties文件。

注意:下面的例子仍然是使用 AntRun 插件,因为此插件能绑定 Maven 生命周期阶段,并通过 Ant 的标签不用编写一点代码即可输出信息、复制文件等,经此而已。其余的与本次构建配置文件无关。

1、配置文件激活

profile 可以让我们定义一系列的配置信息,然后指定其激活条件。这样我们就可以定义多个 profile,然后每个 profile 对应不同的激活条件和配置信息,从而达到不同环境使用不同配置信息的效果。

以下实例,我们将 maven-antrun-plugin:run 目标添加到测试阶段中。这样我们可以在不同的 profile 中输出文本信息。我们将使用 pom.xml 来定义不同的 profile,并在命令控制台中使用 maven 命令激活 profile。

pom.xml 文件如下:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.jsoft.test</groupId>
  5. <artifactId>testproject</artifactId>
  6. <packaging>jar</packaging>
  7. <version>0.1-SNAPSHOT</version>
  8. <name>testproject</name>
  9. <url>http://maven.apache.org</url>
  10. <dependencies>
  11. <dependency>
  12. <groupId>junit</groupId>
  13. <artifactId>junit</artifactId>
  14. <version>3.8.1</version>
  15. <scope>test</scope>
  16. </dependency>
  17. </dependencies>
  18. <profiles>
  19. <profile>
  20. <id>test</id>
  21. <build>
  22. <plugins>
  23. <plugin>
  24. <groupId>org.apache.maven.plugins</groupId>
  25. <artifactId>maven-antrun-plugin</artifactId>
  26. <version>1.8</version>
  27. <executions>
  28. <execution>
  29. <phase>test</phase>
  30. <goals>
  31. <goal>run</goal>
  32. </goals>
  33. <configuration>
  34. <tasks>
  35. <echo>Using env.test.properties</echo>
  36. <copy file="src/main/resources/env.test.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  37. </tasks>
  38. </configuration>
  39. </execution>
  40. </executions>
  41. </plugin>
  42. </plugins>
  43. </build>
  44. </profile>
  45. <profile>
  46. <id>normal</id>
  47. <build>
  48. <plugins>
  49. <plugin>
  50. <groupId>org.apache.maven.plugins</groupId>
  51. <artifactId>maven-antrun-plugin</artifactId>
  52. <version>1.8</version>
  53. <executions>
  54. <execution>
  55. <phase>test</phase>
  56. <goals>
  57. <goal>run</goal>
  58. </goals>
  59. <configuration>
  60. <tasks>
  61. <echo>Using env.properties</echo>
  62. <copy file="src/main/resources/env.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  63. </tasks>
  64. </configuration>
  65. </execution>
  66. </executions>
  67. </plugin>
  68. </plugins>
  69. </build>
  70. </profile>
  71. <profile>
  72. <id>prod</id>
  73. <build>
  74. <plugins>
  75. <plugin>
  76. <groupId>org.apache.maven.plugins</groupId>
  77. <artifactId>maven-antrun-plugin</artifactId>
  78. <version>1.8</version>
  79. <executions>
  80. <execution>
  81. <phase>test</phase>
  82. <goals>
  83. <goal>run</goal>
  84. </goals>
  85. <configuration>
  86. <tasks>
  87. <echo>Using env.prod.properties</echo>
  88. <copy file="src/main/resources/env.prod.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  89. </tasks>
  90. </configuration>
  91. </execution>
  92. </executions>
  93. </plugin>
  94. </plugins>
  95. </build>
  96. </profile>
  97. </profiles>
  98. </project>

注意:构建配置文件采用的是 节点。

说明:上面新建了三个 ,其中 区分了不同的 执行不同的 AntRun 任务;而 AntRun 的任务可以这么理解,AntRun 监听 test 的 Maven 生命周期阶段,当 Maven 执行 test 时,就触发了 AntRun 的任务,任务里面为输出文本并复制文件到指定的位置;而至于要执行哪个 AntRun 任务,此时构建配置文件起到了传输指定的作用,比如,通过命令行参数输入指定的 。

执行命令:

  1. mvn test -Ptest

提示:第一个 test 为 Maven 生命周期阶段,第 2 个 test 为构建配置文件指定的 参数,这个参数通过 -P 来传输,当然,它可以是 prod 或者 normal 这些由你定义的。

运行的结果如下:

Maven - 图3

可以看出成功的触发了AntRun的任务。并且是对应构建配置文件下的 为 test 的任务。

再测试其余两个命令,结果如下:

Maven - 图4

Maven - 图5

2、通过Maven设置激活配置文件

打开 %USER_HOME%/.m2 目录下的 settings.xml 文件,其中 %USER_HOME% 代表用户主目录。如果 setting.xml 文件不存在就直接拷贝 %M2_HOME%/conf/settings.xml 到 .m2 目录,其中 %M2_HOME% 代表 Maven 的安装目录。

配置 setting.xml 文件,增加 <activeProfiles>属性:

  1. <settings xmlns="http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  4. http://maven.apache.org/xsd/settings-1.0.0.xsd">
  5. ...
  6. <activeProfiles>
  7. <activeProfile>test</activeProfile>
  8. </activeProfiles>
  9. </settings>

执行命令:

  1. mvn test

提示 1:此时不需要使用 -Ptest 来输入参数了,上面的 setting.xml 文件的 已经指定了 test 参数代替了。

提示 2:同样可以使用在 %M2_HOME%/conf/settings.xml 的文件进行配置,效果一致。

执行结果:

Maven - 图6

3、通过环境变量激活配置文件

先把上一步测试的 setting.xml 值全部去掉。

然后在 pom.xml 里面的 为 test 的 节点,加入 节点:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.jsoft.test</groupId>
  5. <artifactId>testproject</artifactId>
  6. <packaging>jar</packaging>
  7. <version>0.1-SNAPSHOT</version>
  8. <name>testproject</name>
  9. <url>http://maven.apache.org</url>
  10. <dependencies>
  11. <dependency>
  12. <groupId>junit</groupId>
  13. <artifactId>junit</artifactId>
  14. <version>3.8.1</version>
  15. <scope>test</scope>
  16. </dependency>
  17. </dependencies>
  18. <profiles>
  19. <profile>
  20. <id>test</id>
  21. <activation>
  22. <property>
  23. <name>env</name>
  24. <value>test</value>
  25. </property>
  26. </activation>
  27. <build>
  28. <plugins>
  29. <plugin>
  30. <groupId>org.apache.maven.plugins</groupId>
  31. <artifactId>maven-antrun-plugin</artifactId>
  32. <version>1.8</version>
  33. <executions>
  34. <execution>
  35. <phase>test</phase>
  36. <goals>
  37. <goal>run</goal>
  38. </goals>
  39. <configuration>
  40. <tasks>
  41. <echo>Using env.test.properties</echo>
  42. <copy file="src/main/resources/env.test.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  43. </tasks>
  44. </configuration>
  45. </execution>
  46. </executions>
  47. </plugin>
  48. </plugins>
  49. </build>
  50. </profile>
  51. <profile>
  52. <id>normal</id>
  53. <build>
  54. <plugins>
  55. <plugin>
  56. <groupId>org.apache.maven.plugins</groupId>
  57. <artifactId>maven-antrun-plugin</artifactId>
  58. <version>1.8</version>
  59. <executions>
  60. <execution>
  61. <phase>test</phase>
  62. <goals>
  63. <goal>run</goal>
  64. </goals>
  65. <configuration>
  66. <tasks>
  67. <echo>Using env.properties</echo>
  68. <copy file="src/main/resources/env.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  69. </tasks>
  70. </configuration>
  71. </execution>
  72. </executions>
  73. </plugin>
  74. </plugins>
  75. </build>
  76. </profile>
  77. <profile>
  78. <id>prod</id>
  79. <build>
  80. <plugins>
  81. <plugin>
  82. <groupId>org.apache.maven.plugins</groupId>
  83. <artifactId>maven-antrun-plugin</artifactId>
  84. <version>1.8</version>
  85. <executions>
  86. <execution>
  87. <phase>test</phase>
  88. <goals>
  89. <goal>run</goal>
  90. </goals>
  91. <configuration>
  92. <tasks>
  93. <echo>Using env.prod.properties</echo>
  94. <copy file="src/main/resources/env.prod.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/>
  95. </tasks>
  96. </configuration>
  97. </execution>
  98. </executions>
  99. </plugin>
  100. </plugins>
  101. </build>
  102. </profile>
  103. </profiles>
  104. </project>

执行命令:

  1. mvn test -Denv=test

提示 1:上面使用 -D 传递环境变量,其中 env 对应刚才设置的 值,test 对应。

提示 2:在 Windows 10 上测试了系统的环境变量,但是不生效,所以,只能通过 -D 传递。

执行结果:

Maven - 图7

4、通过操作系统激活配置文件

activation 元素包含下面的操作系统信息。当系统为 windows XP 时,test Profile 将会被触发。

  1. <profile>
  2. <id>test</id>
  3. <activation>
  4. <os>
  5. <name>Windows XP</name>
  6. <family>Windows</family>
  7. <arch>x86</arch>
  8. <version>5.1.2600</version>
  9. </os>
  10. </activation>
  11. </profile>

现在打开命令控制台,跳转到 pom.xml 所在目录,并执行下面的 mvn 命令。不要使用 -P 选项指定 Profile 的名称。Maven 将显示被激活的 test Profile 的结果。

  1. mvn test

5、通过文件的存在或者缺失激活配置文件

现在使用 activation 元素包含下面的操作系统信息。当 target/generated-sources/axistools/wsdl2java/com/companyname/group 缺失时,test Profile 将会被触发。

  1. <profile>
  2. <id>test</id>
  3. <activation>
  4. <file>
  5. <missing>target/generated-sources/axistools/wsdl2java/
  6. com/companyname/group</missing>
  7. </file>
  8. </activation>
  9. </profile>

现在打开命令控制台,跳转到 pom.xml 所在目录,并执行下面的 mvn 命令。不要使用 -P 选项指定 Profile 的名称。Maven 将显示被激活的 test Profile 的结果。

  1. mvn test

Maven POM

POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。

执行任务或目标时,Maven 会在当前目录中查找 POM。它读取 POM,获取所需的配置信息,然后执行目标。

POM 中可以指定以下配置:

  • 项目依赖
  • 插件
  • 执行目标
  • 项目构建 profile
  • 项目版本
  • 项目开发者列表
  • 相关邮件列表信息

在创建 POM 之前,我们首先需要描述项目组 (groupId), 项目的唯一ID。

  1. <project xmlns = "http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
  4. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <!-- 模型版本 -->
  6. <modelVersion>4.0.0</modelVersion>
  7. <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
  8. <groupId>com.companyname.project-group</groupId>
  9. <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
  10. <artifactId>project</artifactId>
  11. <!-- 版本号 -->
  12. <version>1.0</version>
  13. </project>

所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。

节点 描述
project 工程的根标签。
modelVersion 模型版本需要设置为 4.0。
groupId 这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.companyname.project-group 拥有所有的和银行相关的项目。
artifactId 这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置。
version 这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本。例如:com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1

父(Super)POM

父(Super)POM是 Maven 默认的 POM。所有的 POM 都继承自一个父 POM(无论是否显式定义了这个父 POM)。父 POM 包含了一些可以被继承的默认设置。因此,当 Maven 发现需要下载 POM 中的 依赖时,它会到 Super POM 中配置的默认仓库 http://repo1.maven.org/maven2 去下载。

Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被重写。

使用以下命令来查看 Super POM 默认配置:

  1. mvn help:effective-pom

接下来我们创建目录 MVN/project,在该目录下创建 pom.xml,内容如下:

  1. <project xmlns = "http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
  4. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <!-- 模型版本 -->
  6. <modelVersion>4.0.0</modelVersion>
  7. <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
  8. <groupId>com.companyname.project-group</groupId>
  9. <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
  10. <artifactId>project</artifactId>
  11. <!-- 版本号 -->
  12. <version>1.0</version>
  13. </project>

在命令控制台,进入 MVN/project 目录,执行以下命令:

  1. C:\MVN\project>mvn help:effective-pom

Maven 将会开始处理并显示 effective-pom。

  1. [INFO] Scanning for projects...
  2. Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
  3. ...
  4. [INFO] ------------------------------------------------------------------------
  5. [INFO] BUILD SUCCESS
  6. [INFO] ------------------------------------------------------------------------
  7. [INFO] Total time: 01:36 min
  8. [INFO] Finished at: 2018-09-05T11:31:28+08:00
  9. [INFO] Final Memory: 15M/149M
  10. [INFO] ------------------------------------------------------------------------

Effective POM 的结果就像在控制台中显示的一样,经过继承、插值之后,使配置生效。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- ================================================================= -->
  3. <!-- -->
  4. <!-- Generated by Maven Help Plugin on 2012-07-05T11:41:51 -->
  5. <!-- See: http://maven.apache.org/plugins/maven-help-plugin/ -->
  6. <!-- -->
  7. <!-- ================================================================= -->
  8. <!-- ================================================================= -->
  9. <!-- -->
  10. <!-- Effective POM for project -->
  11. <!-- 'com.companyname.project-group:project-name:jar:1.0' -->
  12. <!-- -->
  13. <!-- ================================================================= -->
  14. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/
  15. 2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 h
  16. ttp://maven.apache.org/xsd/maven-4.0.0.xsd">
  17. <modelVersion>4.0.0</modelVersion>
  18. <groupId>com.companyname.project-group</groupId>
  19. <artifactId>project</artifactId>
  20. <version>1.0</version>
  21. <build>
  22. <sourceDirectory>C:\MVN\project\src\main\java</sourceDirectory>
  23. <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
  24. <testSourceDirectory>C:\MVN\project\src\test\java</testSourceDirectory>
  25. <outputDirectory>C:\MVN\project\target\classes</outputDirectory>
  26. <testOutputDirectory>C:\MVN\project\target\test-classes</testOutputDirectory>
  27. <resources>
  28. <resource>
  29. <mergeId>resource-0</mergeId>
  30. <directory>C:\MVN\project\src\main\resources</directory>
  31. </resource>
  32. </resources>
  33. <testResources>
  34. <testResource>
  35. <mergeId>resource-1</mergeId>
  36. <directory>C:\MVN\project\src\test\resources</directory>
  37. </testResource>
  38. </testResources>
  39. <directory>C:\MVN\project\target</directory>
  40. <finalName>project-1.0</finalName>
  41. <pluginManagement>
  42. <plugins>
  43. <plugin>
  44. <artifactId>maven-antrun-plugin</artifactId>
  45. <version>1.3</version>
  46. </plugin>
  47. <plugin>
  48. <artifactId>maven-assembly-plugin</artifactId>
  49. <version>2.2-beta-2</version>
  50. </plugin>
  51. <plugin>
  52. <artifactId>maven-clean-plugin</artifactId>
  53. <version>2.2</version>
  54. </plugin>
  55. <plugin>
  56. <artifactId>maven-compiler-plugin</artifactId>
  57. <version>2.0.2</version>
  58. </plugin>
  59. <plugin>
  60. <artifactId>maven-dependency-plugin</artifactId>
  61. <version>2.0</version>
  62. </plugin>
  63. <plugin>
  64. <artifactId>maven-deploy-plugin</artifactId>
  65. <version>2.4</version>
  66. </plugin>
  67. <plugin>
  68. <artifactId>maven-ear-plugin</artifactId>
  69. <version>2.3.1</version>
  70. </plugin>
  71. <plugin>
  72. <artifactId>maven-ejb-plugin</artifactId>
  73. <version>2.1</version>
  74. </plugin>
  75. <plugin>
  76. <artifactId>maven-install-plugin</artifactId>
  77. <version>2.2</version>
  78. </plugin>
  79. <plugin>
  80. <artifactId>maven-jar-plugin</artifactId>
  81. <version>2.2</version>
  82. </plugin>
  83. <plugin>
  84. <artifactId>maven-javadoc-plugin</artifactId>
  85. <version>2.5</version>
  86. </plugin>
  87. <plugin>
  88. <artifactId>maven-plugin-plugin</artifactId>
  89. <version>2.4.3</version>
  90. </plugin>
  91. <plugin>
  92. <artifactId>maven-rar-plugin</artifactId>
  93. <version>2.2</version>
  94. </plugin>
  95. <plugin>
  96. <artifactId>maven-release-plugin</artifactId>
  97. <version>2.0-beta-8</version>
  98. </plugin>
  99. <plugin>
  100. <artifactId>maven-resources-plugin</artifactId>
  101. <version>2.3</version>
  102. </plugin>
  103. <plugin>
  104. <artifactId>maven-site-plugin</artifactId>
  105. <version>2.0-beta-7</version>
  106. </plugin>
  107. <plugin>
  108. <artifactId>maven-source-plugin</artifactId>
  109. <version>2.0.4</version>
  110. </plugin>
  111. <plugin>
  112. <artifactId>maven-surefire-plugin</artifactId>
  113. <version>2.4.3</version>
  114. </plugin>
  115. <plugin>
  116. <artifactId>maven-war-plugin</artifactId>
  117. <version>2.1-alpha-2</version>
  118. </plugin>
  119. </plugins>
  120. </pluginManagement>
  121. <plugins>
  122. <plugin>
  123. <artifactId>maven-help-plugin</artifactId>
  124. <version>2.1.1</version>
  125. </plugin>
  126. </plugins>
  127. </build>
  128. <repositories>
  129. <repository>
  130. <snapshots>
  131. <enabled>false</enabled>
  132. </snapshots>
  133. <id>central</id>
  134. <name>Maven Repository Switchboard</name>
  135. <url>http://repo1.maven.org/maven2</url>
  136. </repository>
  137. </repositories>
  138. <pluginRepositories>
  139. <pluginRepository>
  140. <releases>
  141. <updatePolicy>never</updatePolicy>
  142. </releases>
  143. <snapshots>
  144. <enabled>false</enabled>
  145. </snapshots>
  146. <id>central</id>
  147. <name>Maven Plugin Repository</name>
  148. <url>http://repo1.maven.org/maven2</url>
  149. </pluginRepository>
  150. </pluginRepositories>
  151. <reporting>
  152. <outputDirectory>C:\MVN\project\target/site</outputDirectory>
  153. </reporting>
  154. </project>

在上面的 pom.xml 中,你可以看到 Maven 在执行目标时需要用到的默认工程源码目录结构、输出目录、需要的插件、仓库和报表目录。

Maven 的 pom.xml 文件也不需要手工编写。

Maven 提供了大量的原型插件来创建工程,包括工程结构和 pom.xml。

Maven 依赖管理

Maven 一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。


可传递性依赖发现

一种相当常见的情况,比如说 A 依赖于其他库 B。如果,另外一个项目 C 想要使用 A ,那么 C 项目也需要使用库 B。

Maven 可以避免去搜索所有所需库的需求。Maven 通过读取项目文件(pom.xml),找出它们项目之间的依赖关系。

我们需要做的只是在每个项目的 pom 中定义好直接的依赖关系。其他的事情 Maven 会帮我们搞定。

通过可传递性的依赖,所有被包含的库的图形会快速的增长。当有重复库时,可能出现的情形将会持续上升。Maven 提供一些功能来控制可传递的依赖的程度。

功能 功能描述
依赖调节 决定当多个手动创建的版本同时出现时,哪个依赖版本将会被使用。 如果两个依赖版本在依赖树里的深度是一样的时候,第一个被声明的依赖将会被使用。
依赖管理 直接的指定手动创建的某个版本被使用。例如当一个工程 C 在自己的依赖管理模块包含工程 B,即 B 依赖于 A, 那么 A 即可指定在 B 被引用时所使用的版本。
依赖范围 包含在构建过程每个阶段的依赖。
依赖排除 任何可传递的依赖都可以通过 “exclusion” 元素被排除在外。举例说明,A 依赖 B, B 依赖 C,因此 A 可以标记 C 为 “被排除的”。
依赖可选 任何可传递的依赖可以被标记为可选的,通过使用 “optional” 元素。例如:A 依赖 B, B 依赖 C。因此,B 可以标记 C 为可选的, 这样 A 就可以不再使用 C。

依赖范围

传递依赖发现可以通过使用如下的依赖范围来得到限制:

范围 描述
编译阶段 该范围表明相关依赖是只在项目的类路径下有效。默认取值。
供应阶段 该范围表明相关依赖是由运行时的 JDK 或者 网络服务器提供的。
运行阶段 该范围表明相关依赖在编译阶段不是必须的,但是在执行阶段是必须的。
测试阶段 该范围表明相关依赖只在测试编译阶段和执行阶段。
系统阶段 该范围表明你需要提供一个系统路径。
导入阶段 该范围只在依赖是一个 pom 里定义的依赖时使用。同时,当前项目的POM 文件的 部分定义的依赖关系可以取代某特定的 POM。

依赖管理

通常情况下,在一个共通的项目下,有一系列的项目。在这种情况下,我们可以创建一个公共依赖的 pom 文件,该 pom 包含所有的公共的依赖关系,我们称其为其他子项目 pom 的 pom 父。 接下来的一个例子可以帮助你更好的理解这个概念。

Maven - 图8

接下来是上面依赖图的详情说明:

  • App-UI-WAR 依赖于 App-Core-lib 和 App-Data-lib。
  • Root 是 App-Core-lib 和 App-Data-lib 的父项目。
  • Root 在它的依赖部分定义了 Lib1、lib2 和 Lib3 作为依赖。