Maven-秘籍-全-

Maven 秘籍(全)

原文:zh.annas-archive.org/md5/a2dca759f12f96089fa330617e3a9c65

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

Apache Maven 食谱集通过一系列食谱描述了 Apache Maven 的功能。这本书将帮助您了解 Apache Maven 是什么,并允许您通过完整且可工作的示例来使用其功能。

本书涵盖内容

第一章, 入门,介绍了在 Microsoft Windows、Mac OS X 或 Linux 上安装 Apache Maven,以及如何使用它创建和构建您的第一个项目。本章还详细说明了安装 Maven 所需的前提软件的步骤。

第二章, Maven 与 IDE 集成,专注于使用 Maven 配置流行的 IDE,并在其中运行 Maven 项目。本章涵盖了 Eclipse、NetBeans 和 IntelliJ IDEA 这三个 IDE。

第三章, Maven 生命周期,涵盖了 Apache Maven 的生命周期,并探讨了阶段和目标的概念。还描述了用户如何使用配置文件来自定义构建。

第四章, 基本 Maven 插件,描述了构建项目所必需的 Maven 插件。对于每个插件,还探讨了各种配置选项。

第五章, 依赖管理,探讨了 Maven 依赖的各种类型,并深入探讨了下载和获取它们的报告。还讨论了在依赖项下载过程中如何处理网络问题。

第六章, 代码质量插件,涵盖了各种代码质量工具(如 Checkstyle、PMD、FindBugs 和 Sonar)的支持。还探讨了每个插件的配置选项以及生成报告。

第七章, 报告和文档,涵盖了 Maven 的报告功能。详细描述了 site 插件及其支持的各项报告。

第八章, 处理典型构建需求,探讨了 Maven 提供的处理选择性源和包含选定资源的构建的功能。还描述了如何使用 Maven 的命令行和帮助功能,以及与软件配置管理系统的接口。

第九章, 多模块项目,描述了构建具有多个模块的大型项目所需的支持。这里还描述了 Maven 对聚合构建和定义父子关系的支持。

第十章, 使用 Maven 进行 Java 开发,描述了构建不同类型的 Java 工件(如 Jar、War 和 Ear)的过程。还描述了 Maven 对在 Jetty 和 Tomcat 中运行项目的支持。

第十一章, 高级 Maven 使用,探讨了 Maven 的高级功能,如创建发行版和强制执行规则。它还描述了如何制作项目发布。

您需要这本书什么

要运行本书中的各种食谱,需要以下内容。除非另有说明,最好使用此处建议的软件的最新版本:

  • 拥有三种操作系统之一(如 Microsoft Windows、Mac OS X 或 Linux)的计算机,最好是最新/受支持的版本

  • Java——具体来说是 Java 开发工具包(JDK)

  • Apache Maven

  • Git——有关版本控制系统的示例

  • 以下一个或多个 IDE:

    • Eclipse

    • NetBeans

    • IntelliJ IDEA

这本书面向谁

Apache Maven 食谱旨在帮助那些寻求了解构建自动化是什么以及如何使用 Apache Maven 实现此目的的人。如果您熟悉 Maven,但想了解其更细微的细微差别以解决特定问题,本书也适合您。如果您正在寻找现成的食谱来解决特定用例,本书也是一本好书。

部分

在本书中,您将找到几个频繁出现的标题(准备工作、如何做、它是如何工作的、还有更多、另请参阅)。

为了清楚地说明如何完成食谱,我们使用以下部分如下:

准备工作

本节告诉您在食谱中可以期待什么,并描述了如何设置任何软件或任何为食谱所需的初步设置。

如何做……

本节包含遵循食谱所需的步骤。

它是如何工作的……

本节通常包含对前一个章节发生情况的详细解释。

还有更多……

本节包含有关食谱的附加信息,以便让读者对食谱有更深入的了解。

另请参阅

本节提供了对其他有用信息的有用链接。

惯例

在本书中,您将找到许多文本样式,用于区分不同类型的信息。以下是一些这些样式的示例及其含义的解释。

文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称如下所示:“前面的输出仍然不会告诉您 Java 的安装位置,这是设置JAVA_HOME所必需的。”

代码块设置如下:

<reporting>
  <plugins>
    <plugin>
      <artifactId>maven-project-info-reports-plugin</artifactId>
      <version>2.0.1</version>
      <reportSets>
        <reportSet></reportSet>
      </reportSets>
    </plugin>
  </plugins>
</reporting>

当我们希望将您的注意力引到代码块的一个特定部分时,相关的行或项目将以粗体显示:

<settings 

 xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository>C:/software/maven</localRepository>
</settings>

任何命令行输入或输出都如下所示:

brew install maven

新术语重要词汇以粗体显示。屏幕上看到的单词,例如在菜单或对话框中,在文本中如下所示:“为了持久化此设置,使用控制面板选项设置环境变量...,如稍后所述的M2_HOME变量。”

注意

警告或重要注意事项以如下方框的形式出现。

小贴士

小贴士和技巧看起来像这样。

读者反馈

读者反馈始终欢迎。让我们知道您对这本书的看法——您喜欢或不喜欢什么。读者反馈对我们很重要,因为它帮助我们开发出您真正能从中获得最大收益的标题。

要向我们发送一般反馈,只需发送电子邮件至<feedback@packtpub.com>,并在邮件主题中提及书的标题。

如果您在某个主题上具有专业知识,并且您有兴趣撰写或为本书做出贡献,请参阅我们的作者指南www.packtpub.com/authors

客户支持

现在您是 Packt 图书的骄傲拥有者,我们有一些事情可以帮助您从您的购买中获得最大收益。

下载示例代码

您可以从您在www.packtpub.com的账户下载示例代码文件,适用于您购买的所有 Packt 出版图书。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给您。

下载本书的颜色图像

我们还为您提供了一个包含本书中使用的截图/图表的颜色图像的 PDF 文件。这些颜色图像将帮助您更好地理解输出的变化。您可以从www.packtpub.com/sites/default/files/downloads/ApacheMavenCookbook_ColorImages.pdf下载此文件。

勘误

尽管我们已经尽一切努力确保我们内容的准确性,但错误仍然会发生。如果您在我们的书中发现错误——可能是文本或代码中的错误——如果您能向我们报告这一点,我们将不胜感激。通过这样做,您可以节省其他读者的挫败感,并帮助我们改进本书的后续版本。如果您发现任何勘误,请通过访问www.packtpub.com/submit-errata,选择您的书,点击勘误提交表单链接,并输入您的勘误详情来报告它们。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站或添加到该标题的勘误部分下的现有勘误列表中。

要查看之前提交的勘误表,请访问www.packtpub.com/books/content/support,并在搜索字段中输入书的名称。所需信息将出现在勘误部分下。

侵权

在互联网上侵犯版权材料是一个跨所有媒体持续存在的问题。在 Packt,我们非常重视我们版权和许可证的保护。如果您在互联网上发现任何形式的我们作品的非法副本,请立即提供位置地址或网站名称,以便我们可以追究补救措施。

请通过链接将疑似盗版材料发送至 <copyright@packtpub.com> 与我们联系。

我们感谢您在保护我们作者和我们为您提供有价值内容的能力方面的帮助。

问题

如果您对本书的任何方面有问题,您可以通过 <questions@packtpub.com> 与我们联系,我们将尽力解决问题。

第一章. 入门

在本章中,我们将介绍与 Apache Maven 入门相关的基本任务:

  • 在 Microsoft Windows 上安装 Maven

  • 在 Mac OS X 上安装 Maven

  • 在 Linux 上安装 Maven

  • 更改 Maven 使用的 JDK

  • 使用 Maven 创建一个简单的项目

  • 使用 Maven 构建一个简单的项目

  • 更改 Maven 仓库的位置

  • 在 HTTP 代理服务器后面运行 Maven

  • 理解标准目录结构

简介

Apache Maven 是构建自动化领域的一个流行工具,主要用于 Java 项目。Maven 解决了构建软件的两个方面。首先,它描述了软件是如何构建的,其次,它描述了其依赖关系。它使用约定来描述构建过程。一个 XML 文件描述了正在构建的软件项目,它对其他外部模块和组件的依赖关系,构建顺序,目录和所需的插件。它包含预定义的目标来执行某些定义明确的任务,例如代码编译和打包。Maven 从一个或多个仓库(如Maven Central Repository)动态下载 Java 库和 Maven 插件,并将它们存储在本地。

自从 2004 年 Maven 1.0 版本发布以来,它已经获得了广泛的认可,并且如今已成为大量开源和商业项目的构建工具。

如果你正在阅读这本书,那么你并不是来了解为什么需要 Maven 的。你是来探索 Maven 并释放它所提供的潜力的。本书的目标是让读者了解 Maven 的各种特性,包括安装、配置以及通过示例、插图和工作项目进行简单到复杂的用法。

与其他构建自动化工具的简要比较

让我们简要讨论一些构建自动化工具:

  • Make:如果你来自 C 编程世界,那么你很可能使用过 Make。Makefiles 不是平台无关的。它们与 Windows 原生不兼容。因此,它们不适合构建 Java 项目。

  • Ant:这是基于 Make 的,有目标和依赖关系。每个目标都有一组任务。Ant 没有约定。它是过程性的,并且没有构建生命周期的概念。Maven 有约定,是声明性的,并且有生命周期。

在本章中,我们将介绍 Maven 的基础知识——安装软件、验证安装以及创建、实现和构建一个简单的 Java 项目。我们还将介绍一些高级主题,例如更改仓库位置或在 HTTP 代理服务器后面运行 Maven,这对于那些对 Maven 默认工作方式有问题的用户可能是有用的。

让我们首先设置 Maven。我们将介绍如何在三个流行的操作系统上完成这一操作,即 Microsoft Windows、Mac OS X 和 Linux。

在 Microsoft Windows 上安装 Maven

在撰写本书时,Microsoft Windows 8.1 是 Microsoft Windows 的最新版本。虽然截图和输出将是针对 Microsoft Windows 8.1 的,但步骤对于早期(以及可能更晚)的版本也是相似的。

准备就绪

由于 Maven 需要一个 Java 平台,首先请确保您已经在系统上安装了 Java 环境,特别是Java 开发工具包JDK);Java 运行环境JRE)是不够的。

您可以通过打开 添加或删除程序 来验证 Java 是否已安装在您的系统上。如果您看到以下截图类似的内容,JDK 已安装在您的系统上:

准备就绪

您还可以从 Microsoft Windows 资源管理器验证程序文件夹结构:

准备就绪

如何操作...

让我们从执行以下步骤开始安装 Java 和 Maven:

  1. 将变量 JAVA_HOME 设置为指向 Maven 要使用的 Java 安装;例如,您可以通过以下方式设置 JAVA_HOME 变量:

    C:\projects\apache_maven_cookbook>set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_20
    
    

    注意

    注意,此设置在关闭命令提示符后不会持久化。要持久化此设置,请使用 控制面板 选项中的 环境变量...,如稍后所述的 M2_HOME 变量。

  2. 如果您的系统上未安装 JDK,现在是时候从 Oracle Java SE 下载页面 www.oracle.com/technetwork/java/javase/downloads/index.html 下载并安装它了。

    安装完成后,请确保 JAVA_HOME 已按前面所述设置。

    现在我们已经设置了 Java,让我们下载并设置 Maven。

  3. 前往 maven.apache.org/ 并点击 下载 链接。

  4. 显示了 Maven 最新稳定版本的链接。

  5. 二进制文件以 .zip.tar.gz 格式提供。选择其中之一。

  6. 将下载的二进制文件解压到您希望 Maven 存放的文件夹中。在这个例子中,我选择了 C:\software

    提示

    最好避免使用含有空格的文件夹,因为 Maven 或其插件的某些功能可能无法正常工作。

  7. 确保内容与以下截图类似:如何操作...

上一张截图显示了 Maven 包含的目录列表。

现在我们简要讨论一下这些目录包含的内容:

  • bin 文件夹包含在各个平台上运行 Maven 所需的批处理文件和 shell 脚本。

  • boot 文件夹包含 Maven 启动所需的 jar 文件。

  • conf 文件夹包含 Maven 使用的默认 settings.xml 文件。

  • lib 文件夹包含 Maven 使用的库。它还包含一个 ext 文件夹,其中可以放置第三方扩展,这些扩展可以扩展或覆盖默认的 Maven 实现。

现在我们来确保可以从命令提示符运行 Maven,通过执行以下步骤:

  1. 打开 控制面板如何操作...

  2. 选择 高级系统设置如何操作...

  3. 点击 环境变量...。添加 M2_HOME 变量并将其设置为 Maven 提取的文件夹。如何操作...

  4. 编辑 PATH 变量以包括 Maven 的 bin 文件夹。如何操作...

它是如何工作的...

Maven 安装本质上是一组 JAR 文件、配置文件和一个 Microsoft Windows 批处理文件 mvn.bat

mvn 命令本质上运行这个批处理文件。它首先检查 JAVA_HOME。此文件位于 Maven 安装的 bin 文件夹中,因此它需要位于 PATH 中。

如果批处理文件找不到 JAVA_HOME,它会在其 PATH 中查找 Java。这可能导致意外结果,因为通常 PATH 中的 Java 是 JRE 而不是 JDK。

批处理文件接着查找 M2_HOME,这是 Maven 安装的位置。它这样做是为了能够加载存在的库。

此外,它还会读取在 MAVEN_OPTS 中指定的值。此变量允许您使用额外的堆大小和其他 Java 参数运行 Maven。

使用 JAVA_HOMEM2_HOMEMaven_OPTS 的值,批处理文件会运行其主类 org.codehaus.plexus.classworlds.launcher.Launcher

更多内容...

使用以下步骤验证您的 Maven 安装:

  1. 在 Microsoft Windows 中打开命令提示符并运行以下命令:

    C:\software\apache-maven-cookbook>mvn -version
    
    
  2. 应该显示以下输出:

    Apache Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T22:59:23+05:30)
    Maven home: C:\software\apache-maven-3.2.5
    Java version: 1.7.0_67, vendor: Oracle Corporation
    Java home: C:\Program Files\Java\jdk1.7.0_67\jre
    Default locale: en_IN, platform encoding: Cp1252
    OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "windows"
    
    

相关阅读

  • 本章中 使用 Maven 创建简单项目 的配方

在 Mac OS X 上安装 Maven

让我们看看在 Mac OS X 上安装 Maven 的步骤。这适用于最新的 Mac OS X 版本,即 Yosemite。

以前,苹果为 Mac 提供了 Java,但从 Java 7 开始停止了这一做法。苹果 Java 不适用于最新的 Mac OS X 版本。

准备中

让我们检查您的 Mac 上是否有 Java 环境:

  1. 打开终端并运行以下命令:

    /usr/libexec/java_home -v 1.7
    
    
  2. 查看您是否得到以下类似的输出:

    /Library/Java/JavaVirtualMachines/jdk1.7.0_71.jdk/Contents/Home
    
    
  3. 运行以下命令以检查您是否有 Java 8:

    /usr/libexec/java_home -v 1.8
    
    
  4. 如果存在 Java,这将给出以下输出:

    /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home
    

    如您所见,我的系统上既有 Java 1.7 也有 1.8。

  5. JAVA_HOME 设置为所需的 JDK。这可以通过两种方式完成,具体取决于您的需求:

    如果这是会话期间的临时设置,请运行以下命令:

    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home
    
    

    如果这是永久的,请将前面的行添加到您的 HOME 文件夹中的 .bash_profile

小贴士

确保您有 JDK 安装而不是 JRE。

如果没有 Java,请从 Oracle Java 下载页面 www.oracle.com/technetwork/java/javase/downloads/index.html 下载并安装 Java。

安装完成后,按照前面的步骤验证 Java 安装。

现在,让我们在 Mac OS X 上设置 Maven。

如何操作...

按照以下步骤从其官方网站下载 Maven:

  1. 前往 maven.apache.org/ 并点击 下载 链接。将显示 Maven 的最新稳定版本的链接。

  2. 二进制文件以 .zip.tar.gz 格式提供。选择其中之一。

  3. 将下载的二进制文件提取到你想让 Maven 存放的文件夹中。对于 Mac 来说,通常是 /usr/local 文件夹。

  4. 你需要超级用户(su)或管理员权限才能将内容放置在 /usr/local 文件夹中。如果没有权限,可以将内容放置在 HOME 文件夹的子文件夹中。

  5. 通过执行以下命令确保内容与以下输出类似:

    /usr/local/apache-maven-3.2.5$ ls -l
    
    

    输出如下所示:

    total 27
    -rw-r--r--    1 root    wheel    17464 Aug 12 02:29 LICENSE
    -rw-r--r--    1 root    wheel      182 Aug 12 02:29 NOTICE
    -rw-r--r--    1 root    wheel     2508 Aug 12 02:26 README.txt
    drwxr-xr-x    8 root    wheel     4096 Aug 19 13:41 bin
    drwxr-xr-x    3 root    wheel        0 Aug 19 13:41 boot
    drwxr-xr-x    4 root    wheel        0 Oct 14 17:39 conf
    drwxr-xr-x   67 root    wheel    28672 Aug 19 13:41 lib
    
    
  6. 按如下设置 M2_HOME 变量:

    export M2_HOME=/usr/local/apache-maven-3.2.5
    
    
  7. PATH 更新为包括 Maven 的 bin 文件夹:

    export PATH=$PATH:$M2_HOME/bin
    
    

小贴士

JAVA_HOME 一样,前面的设置可以通过更新 .bash_profile 中的前几行来持久化。

在前面的步骤中,我们讨论了从官方网站下载 Maven 的步骤。现在,我们将讨论使用 brew 安装 Maven。Brew 是 Mac OS X 上安装开源软件的流行应用程序。如果你在 Mac OS X 上安装了 brew,运行以下命令来安装 Maven:

brew install maven

前一个命令的输出将显示如下截图:

如何操作...

它是如何工作的...

Maven 安装本质上是一组 JAR 文件、配置文件和一个 Mac OS X shell 脚本,即 mvn

mvn 命令本质上运行这个脚本。它首先检查 JAVA_HOME。这个文件位于 Maven 安装的 bin 文件夹中,因此它需要位于 PATH 中。

如果 shell 脚本找不到 JAVA_HOME,它会在其 PATH 中查找 Java。这可能会导致意外结果,因为通常 PATH 中的 Java 是 JRE 安装,而不是 JDK。

然后 shell 脚本会查找 M2_HOME,这是 Maven 安装的位置。这样做是为了能够加载现有的库。

此外,它还会读取在 MAVEN_OPTS 中指定的值。这个变量允许你以额外的堆大小和其他 Java 参数运行 Maven。

使用 JAVA_HOMEM2_HOMEMAVEN_OPTS 的值,shell 脚本运行其主类 org.codehaus.plexus.classworlds.launcher.Launcher

更多内容...

使用以下步骤验证你的 Maven 安装:

  1. 打开命令提示符并运行以下命令:

    mvn –version
    
    
  2. 前一个命令的输出应显示如下截图所示:更多内容...

参见

  • 本章中 使用 Maven 创建简单项目 的配方

在 Linux 上安装 Maven

让我们看看在 Linux 上安装 Maven 的步骤。

尽管有众多 Linux 版本(Ubuntu、Fedora、RHEL、SUSE、CentOS 等),但设置 Maven 的步骤是相似的。

准备工作

Maven 需要 Java,特别是 Java 开发工具包 (JDK)。使用以下步骤,让我们检查它是否已安装在你的 Linux 系统中,这有点复杂:

  1. 打开终端并运行以下命令:

    java -version
    
    
  2. 检查你是否得到了以下类似的输出:

    java version "1.7.0_65"
    OpenJDK Runtime Environment (rhel-2.5.1.2.el6_5-x86_64 u65-b17)
    
    

    前一个输出仍然无法告诉你 Java 的安装位置,这是设置 JAVA_HOME 所必需的。你可以通过执行以下步骤来获取这个信息。

  3. 检查 javac 是否工作;它只有在 JDK 安装的情况下才会工作,而不是 JRE:

    $ javac -version
    
    

    前一个命令的输出如下所示:

    javac 1.7.0_65
    
    
  4. 查找 javac 命令的位置:

    $ which javac
    
    

    前一个命令的输出如下所示:

    /usr/bin/javac
    
    
  5. 在前面的输出中,javac 是指向文件实际位置的符号链接。你可以通过以下方式尝试确定这个位置:

    $ readlink /usr/bin/javac
    
    

    前一个命令的输出如下所示:

    /etc/alternatives/javac
    
    
  6. 通过执行前面的命令,我们再次得到了符号链接。要获取 javac 位置的路径,我们再次执行以下命令:

    $ readlink /etc/alternatives/javac
    
    

    前一个命令的输出如下所示:

    /usr/lib/jvm/java-1.7.0-openjdk.x86_64/bin/javac
    
    
  7. 我们现在已经找到了 JDK 安装的文件夹:

    /usr/lib/jvm/java-1.7.0-openjdk.x86_64/
    
    
  8. JAVA_HOME 设置为上一个文件夹。这可以通过两种方式完成,具体取决于你的需求:

    如果这是会话期间的临时设置,请运行以下命令:

    export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk.x86_64/
    
    

    如果这是永久的,请将前面的行添加到你的 HOME 文件夹中的 .bash_profile 文件中。

如果 Java 不存在,请从 Oracle Java 下载页面 www.oracle.com/technetwork/java/javase/downloads/index.html 下载并安装 Java。

如果你有一个基于 rpm 的 Linux 发行版,你可以下载并安装 rpm。否则,你可以下载发行版的 .tar.gz 格式并将其解压到你选择的文件夹中。

在前面的例子中,你知道 Java 的确切安装位置,并可以相应地设置 JAVA_HOME。一旦安装,可以通过遵循前面的步骤来验证 Java 安装。

现在,让我们在 Linux 上设置 Maven。

如何做到这一点...

要在 Linux 上设置 Maven,请执行以下步骤:

  1. 前往 maven.apache.org/ 并点击 下载 链接。将显示 Maven 最新稳定版本的链接。

  2. 二进制文件以 .zip.tar.gz 格式提供。对于 Mac OS X 和 Linux,首选的下载格式是 .tar.gz

  3. 将下载的二进制文件解压到你希望 Maven 存放的文件夹中。在 Linux 中,典型的位置是 /usr/local 文件夹。

    小贴士

    你需要超级用户 (su) 或管理员权限才能将内容放置在 /usr/local 文件夹中。如果你没有权限,你可以在 HOME 文件夹的子文件夹中放置它。

  4. 执行以下命令,并确保 apache-maven-3.2.5 文件夹的内容与以下输出类似:

    /usr/local/apache-maven-3.2.5$ ls -l
    
    

    前一个命令的输出如下所示:

    total 27
    -rw-r--r--    1 root    root    17464 Aug 12 02:29 LICENSE
    -rw-r--r--    1 root    root      182 Aug 12 02:29 NOTICE
    -rw-r--r--    1 root    root     2508 Aug 12 02:26 README.txt
    drwxr-xr-x    8 root    root     4096 Aug 19 13:41 bin
    drwxr-xr-x    3 root    root        0 Aug 19 13:41 boot
    drwxr-xr-x    4 root    root        0 Oct 14 17:39 conf
    drwxr-xr-x   67 root    root    28672 Aug 19 13:41 lib
    
    
  5. M2_HOME 变量设置如下:

    export M2_HOME=/usr/local/apache-maven-3.2.5
    
    
  6. 更新 PATH 以包括 Maven 的 bin 文件夹:

    export PATH=$PATH:$M2_HOME/bin
    
    

JAVA_HOME 类似,前面的设置可以通过更新 .bash_profile 来持久化。

它是如何工作的...

Maven 的安装本质上是一组 JAR 文件、配置文件和一个 Linux shell 脚本,即 mvn

mvn 命令本质上运行此脚本。它首先检查 JAVA_HOME。此文件位于 Maven 安装的 bin 文件夹中,因此需要位于 PATH 中。

如果 shell 脚本找不到 JAVA_HOME,它会在其 PATH 中查找 java。这可能会导致意外结果,因为通常 PATH 中的 Java 是 JRE 而不是 JDK。

shell 脚本随后会查找 M2_HOME,这是 Maven 安装的位置。它这样做是为了能够加载现有的库。

此外,它还会读取在 MAVEN_OPTS 中指定的值。此变量允许您使用额外的堆大小和其他 Java 参数运行 Maven。

使用 JAVA_HOMEM2_HOMEMAVEN_OPTS 的值,shell 脚本运行其 org.codehaus.plexus.classworlds.launcher.Launcher 主类。

还有更多...

使用以下步骤,让我们通过运行 Maven 命令来确认 Maven 是否已正确设置:

  1. 打开命令提示符并运行以下命令:

    mvn –version
    
    
  2. 应显示以下输出:

    Apache Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T22:59:23+05:30)
    Maven home: /usr/local/maven
    Java version: 1.7.0_65, vendor: Oracle Corporation
    Java home: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.65.x86_64/jre
    Default locale: en_US, platform encoding: ANSI_X3.4-1968
    OS name: "linux", version: "2.6.32-279.22.1.el6.x86_64", arch: "amd64", family: "unix"
    
    

如果您遇到错误,请重新检查安装步骤并重复执行。

参见

  • 本章中 使用 Maven 创建一个简单项目 的配方

更改 Maven 使用的 JDK

您的系统上可以安装多个 JDK 版本。通过遵循一些简单的步骤,您可以指定和/或更改 Maven 使用的 JDK。

如何操作...

您会记得,在早期部分,我们使用了 Java SE 7。现在让我们将其更改为 Java SE 8。要在 Microsoft Windows 上将 JDK 版本更改为 Java SE 8,请执行以下步骤:

  1. 从命令提示符运行以下命令:

    set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_20
    
    
  2. 对于 Linux 或 Mac,命令将是:

    export JAVA_HOME=<java-8-home-folder>
    
    
  3. 现在,运行以下命令以检查已安装的 Maven 版本:

    mvn –version
    
    
  4. 要检查 Microsoft Windows 上安装的 Maven 版本,请在命令提示符中运行以下命令。您应该得到以下输出。Linux 和 Mac 的输出将类似:

    C:\projects\apache-maven-cookbook>mvn -version
    
    

    前一个命令的输出如下所示:

    Apache Maven 3.2.5 (12a6b3acb947671f09b81f49094c53f426d8cea1; 2014-12-14T22:59:23+05:30)
    Maven home: C:\software\apache-maven-3.2.5
    Java version: 1.8.0_20, vendor: Oracle Corporation
    Java home: C:\Program Files\Java\jdk1.8.0_20\jre
    Default locale: en_IN, platform encoding: Cp1252
    OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "windows"
    
    

它是如何工作的...

Maven 总是使用由 JAVA_HOME 指定的 JDK,无论系统上有多少 JDK 安装。这使用户能够根据需要或基于项目更改 JDK。

因此,确保 JAVA_HOME 已定义非常重要。如果没有这个变量,Maven 将尝试从 PATH 中检测 Java 的存在。这通常是 JRE 而不是 JDK。

使用 Maven 创建一个简单的项目

现在我们已经在我们的首选操作系统上设置了 Maven 并验证了它运行良好,是时候创建一个简单的 Java 项目了。

Maven 通过创建一系列遵循接受惯例的文件和文件夹,使启动新项目变得容易。

如何操作...

让我们开始使用 Maven 创建第一个简单项目,按照以下步骤操作:

  1. 打开命令提示符,并将目录更改为你想要创建第一个 Maven 项目的文件夹。

  2. 运行以下命令:

    mvn archetype:generate -DgroupId=com.packt.cookbook -DartifactId=simple-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
    
    

    你可以根据需要更改前面命令中的groupIdartifactId值。

  3. 你将看到 Maven 下载了一堆文件:

    Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
    Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom (4 KB at 1.4 KB/sec)
    
    
  4. 然后,它将开始生成源代码:

    [INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) > generate-sources
    @ standalone-pom >>>
    
    
  5. 当 Maven 完成生成源代码后,它将创建我们想要的项目:

    [INFO] Using following parameters for creating project from Old (1.x) Archetype:
    maven-archetype-quickstart:1.0
    [INFO] ----------------------------------------------------------------------------
    [INFO] Parameter: groupId, Value: com.packt.cookbook
    [INFO] Parameter: packageName, Value: com.packt.cookbook
    [INFO] Parameter: package, Value: com.packt.cookbook
    [INFO] Parameter: artifactId, Value: simple-project
    [INFO] Parameter: basedir, Value: C:\projects\apache-maven-cookbook
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] project created from Old (1.x) Archetype in dir: C:\projects\apache-maven-cookbook\simple-project
    
    

小贴士

下载示例代码

你可以从www.packtpub.com下载示例代码文件,这是你购买的所有 Packt Publishing 书籍的账户。如果你在其他地方购买了这本书,你可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给你。

如何工作...

在运行前面命令创建简单项目时,你是否遇到了错误?

一种可能性是,你的 Maven 位于 HTTP 代理服务器后面。如果是这样,请参阅本章中的“在 HTTP 代理服务器后面运行 Maven”配方。

让我们看看创建的文件夹结构:

如何工作...

你会注意到以下事项:

  • Maven 项目配置文件pom.xmlsimple-project文件夹的根目录下创建。我们将在后续章节中详细探讨这个文件。

  • 创建了一堆文件夹:

    • src\main\java:这是用于 Java 源文件的目录

    • src\test\java:这是用于 Java 测试源文件的目录

    • src\main\resources:这是用于项目的资源文件

    • src\test\resources:这是用于测试的资源文件

  • 在上述每个文件夹中,创建了一个与groupIdorg.packt.cookbook)相对应的文件夹结构。

以下基本上是 Maven 约定在起作用:

  • Maven 期望所有 Java 源文件都位于src\main\java

  • 同样,它期望所有 Java 测试文件都位于src\test\java

  • 它期望所有项目资源都位于src\main\resources,测试资源位于src\test\resources

  • 它期望源文件通常具有与groupId参数相同的包结构(尽管这不是强制性的)

  • 创建了两个示例类,分别是App.javaAppTest.java,并且预期它们不会用于测试 Maven 的工作之外

我们在本章的“使用 Maven 创建简单项目”配方中使用的mvn命令,试图使用指定的命令行参数调用archetype插件的generate目标。

默认的 Maven 安装具有最小功能。Maven 的所有功能都作为 Maven 插件提供。当给出插件名称时,Maven 知道从哪里下载它,然后运行它。

在这种情况下,Maven 下载了 archetype 插件。此插件反过来又可以依赖于另一个插件。在这种情况下,后者插件被下载。这以递归的方式发生,并且在过程结束时,下载了运行指定命令所需的所有相关插件。

这些插件被放置在你的本地仓库中,这是你的系统中的一个位置。一旦下载,除非被删除,否则将不再下载。

相关阅读

  • 本章中关于在 HTTP 代理服务器后面运行 Maven的配方

使用 Maven 构建简单的项目

让我们现在构建前面部分创建的项目。

如何做...

要使用 Maven 构建之前创建的简单项目,执行以下步骤:

  1. 打开命令提示符并运行以下命令,将目录更改为项目创建的文件夹:

    mvn package
    
    
  2. 在输出中观察以下内容:

    注意以下警告(我们将在本书的后面部分看到如何解决它):

    [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ simple-project ---
    [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
    i.e. build is platform dependent!
    
    

    检查源是否已编译:

    [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ simple-project
    
    

    检查测试是否已运行:

    [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ simple-project ---
    [INFO] Surefire report directory: C:\projects\apache-maven-cookbook\simple-project\target\surefire-reports
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running com.packt.cookbook.AppTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
    
    
  3. 现在已创建了一个 JAR 文件。

它是如何工作的...

mvn package 命令中,package 参数是构建生命周期中的一个阶段。Maven 有一个默认的构建生命周期,包含多个阶段。每个阶段将按顺序执行它之前的所有阶段以及指定的阶段。在这种情况下,package 阶段按以下顺序执行:

  • 验证

  • 编译

  • 测试

validate 阶段确保项目(特别是描述项目的 pom.xml 文件)处于良好状态,并且运行项目所需的所有必要信息都可用。

compile 阶段编译源代码。

test 阶段编译测试源代码,然后使用合适的测试框架运行测试。在早期示例中,使用 JUnit 框架运行测试。

package 阶段将工件打包到 pom.xml 文件中指定的格式。

更改 Maven 仓库的位置

有三种类型的 Maven 仓库:

  • 本地:这是你的计算机文件系统中的仓库

  • 远程:这是下载所需 Maven 文件的仓库

  • 镜像:这些是仓库管理器,例如 NexusArtifactory,它们镜像各种仓库

你已经看到 Maven 下载了许多文件(称为 poms 和 jars)。让我们看看它们在你的计算机中的位置:

  • 在 Microsoft Windows 中,转到你的 HOME 文件夹(C:\Users\username),对于 Mac 是 /Users/username,对于 Linux 是 /home/username(或类似位置)

  • 你将注意到 .m2 文件夹,在其中,有一个名为 repository 的子文件夹

    小贴士

    任何以点(.)开头的文件夹通常都会被隐藏起来。你需要更改文件夹查看器设置才能看到它。

  • 你将看到许多由 Maven 使用的文件夹和文件

你可能希望出于以下原因更改此位置:

  • 您可能想要在 Microsoft Windows 中节省 C 驱动器的空间,并将这些文件夹和文件存储在 D 驱动器上。

  • 您可能想要备份内容。备份软件通常会在文件系统的特定文件夹中备份内容。

  • 您的组织可能有一项政策,要求所有用户将本地仓库存储在同一个文件夹中。

如何操作...

要更改 Maven 仓库的位置,请执行以下步骤:

  1. .m2 文件夹中创建一个名为 settings.xml 的文件。

  2. 将以下内容添加到您刚刚创建的 settings.xml 文件中:

    <settings 
    
     xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          http://maven.apache.org/xsd/settings-1.0.0.xsd">
        <localRepository>C:/software/maven</localRepository>
    </settings>
    

    注意前面代码中高亮的部分。我们已经将仓库内容的位置更改为 C:\software\maven。您可以将它更改为任何有效的文件夹名称。

  3. 删除 repository 子文件夹,然后再次运行 mvn package 命令。

    您现在会注意到,repository 文件夹并没有创建在 .m2 文件夹中。相反,它被创建在 C:\software\maven

它是如何工作的...

Maven 以以下方式确定本地仓库的位置:

  • 如果用户 .m2 文件夹中存在 settings.xml 文件,其中包含 <localRepository> 标签,那么 Maven 将使用其内容来确定位置

  • 如果没有,Maven 将检查默认的 settings.xml 文件中是否明确定义了 localRepository,该文件位于 Maven 安装目录的 conf 文件夹中。

  • 如果本地仓库不存在,Maven 将使用默认值,即用户的 .m2 文件夹

在 HTTP 代理服务器后面运行 Maven

大多数组织出于安全和其它原因不允许其网络中的设备直接访问互联网。在这种情况下,通常会出现代理服务器。代理服务器的详细信息在浏览器或任何需要互联网访问的其他位置指定。

如何操作...

让我们通过以下步骤在 HTTP 代理服务器后面运行 Maven:

  1. 如果您的 HOME 目录中的 .m2 文件夹中尚未创建 settings.xml 文件,请创建一个。

  2. settings 标签内添加以下代码:

      <proxies>
        <proxy>
          <id>myproxy</id>
          <active>true</active>
          <protocol>http</protocol>
          <host>proxy.myorg.com</host>
          <port>8080</port>
          <username>proxyuser</username>
          <password>somepassword</password>
          <nonProxyHosts>*.myorg.com </nonProxyHosts>
        </proxy>
      </proxies>
    

如果代理服务器不需要身份验证,可以省略 usernamepassword 标签。

nonProxyHosts 标签允许您指定可以直接访问的位置(例如,您的内部网络)。如果不相关,可以跳过。

它是如何工作的...

Maven 需要互联网访问来下载插件和依赖项。当 Maven 运行时,它会读取用户的 settings.xml 文件(如果存在)。它会检查任何活动的代理设置并应用相同的设置。

Maven 使用代理设置中的值从仓库下载任何工件。如果没有要下载的工件,则不使用这些值。

注意

HTTP 代理服务器可能只在您的组织网络中工作。如果您从不同的网络运行 Maven,您可能希望关闭 HTTP 代理服务器。这可以通过在前面代码中将 active 标签设置为 false 来完成。

理解标准目录布局

当我们之前构建我们的示例 Java 项目时,我们看到了文件被编译、测试被执行,以及 JAR 文件被生成。我们不知道这些工件是在哪里创建的。

如何操作...

让我们通过以下步骤找到工件创建的位置:

  1. 前往包含示例 Maven 项目的文件夹。

  2. 打开创建的 target 子文件夹:如何操作...

它是如何工作的...

当 Maven 运行时,它会将所有生成的内容放入一个单独的文件夹中。这是为了将其与用户生成的任何内容区分开来。让我们检查这个文件夹的内容:

  • classes 文件夹:编译后的源文件放置在这个文件夹中。这个文件夹还将包含资源,例如 XML 和属性文件,这些文件是源代码的一部分,放置在 src/main/resources 中。

  • test-classes 文件夹:编译后的测试源文件存放在这个文件夹中。此外,它还包含测试资源,这些是用于测试目的但不是用于运行项目的文件。

  • surefire-reports 文件夹:测试报告被单独放置在这个文件夹中。通常,这里提供 XML 和 HTML 报告格式。后者可以在浏览器中打开,而前者可以与代码覆盖率工具集成。

  • 输出的 .jar 文件:生成的项目工件也存在于这个文件夹中。

  • 另外两个文件夹——maven-archivermaven-status——包含 Maven 在构建过程中使用的信息。

第二章。Maven 与 IDE 集成

在本章中,我们将了解如何使用三个流行的 Java 集成开发环境IDE)设置和使用 Maven。我们将涵盖以下菜谱:

  • 在 Eclipse 中创建新的 Maven 项目

  • 在 Eclipse 中导入现有的 Maven 项目

  • 在 NetBeans 中导入现有的 Maven 项目

  • 在 NetBeans 中导入现有的 Maven 项目

  • 在 IntelliJ IDEA 中创建新的 Maven 项目

  • 在 IntelliJ IDEA 中导入现有的 Maven 项目

简介

IDE 通过执行以下功能提高开发者的生产力:

  • 创建样板代码

  • 执行代码补全

  • 识别语法问题

  • 执行编译、单元测试和部署到 Web/应用程序服务器等任务

虽然 Maven 主要是一个命令行工具,但 IDE 可以帮助开发者以更好的方式享受和利用 Maven 功能。Maven 与 IDE 的集成可以帮助我们自动下载依赖项,并通过 UI 快速搜索依赖项,以及其他好处。

Maven 的 IDE 集成在过去几年中得到了改善,现在大多数 Maven 功能都可以通过 IDE 设置。

在 Eclipse 中创建新的 Maven 项目

Eclipse 是最受欢迎的开源 IDE 之一。它主要起源于 IBM 的 VisualAge for Java。它是一个可以通过插件进行扩展的平台(Maven 也是如此)。Eclipse 不仅可以用于开发 Java 项目,还可以通过插件开发大量其他语言。

就本书撰写时,Eclipse 4.4.1(Luna SR1)是最新的版本。本书中的截图为此版本。

准备就绪

由于 Eclipse 需要 Java 环境来运行,因此需要在系统上安装 Java。要完成此操作,请参阅第一章的前三个菜谱的准备就绪部分,入门

www.eclipse.org/downloads/下载 Eclipse。Eclipse 的二进制文件适用于所有流行的操作系统。还有针对不同类型开发者的不同 Eclipse 包解决方案(C/C++、Java EE、PHP 等)。您应该选择 Java 开发者使用的 Eclipse IDE 或 Java EE 开发者使用的 Eclipse IDE。

小贴士

要使 Maven 工作,重要的是使用 JDK 而不是 JRE 启动 Eclipse。这可以通过将以下参数传递给启动脚本来完成:

-vm %JAVA_HOME%\bin\javaw

最近的 Eclipse 版本预装了 Maven 支持。让我们通过以下步骤来确认这一点:

  1. 启动 Eclipse,然后在帮助菜单中点击关于 Eclipse按钮,如图所示:准备就绪

  2. 从您看到的图标列表中点击m2图标:准备就绪

  3. 点击m2图标,您应该会看到以下类似的截图:准备就绪

  4. 通过导航到 Eclipse 菜单栏的窗口 | 首选项来点击Maven链接。

  5. 点击安装。您将看到 Eclipse 中可用的现有安装。它使用 Eclipse 附带的嵌入式Maven 安装,如下面的截图所示:准备就绪

  6. 通过点击添加…按钮添加您设置的 Maven 安装。准备就绪

  7. 您可以检查此安装,以便它被选择而不是嵌入式安装。

如何操作…

要创建一个新的 Maven 项目,请执行以下步骤:

  1. 导航到文件 | 新建 | Maven 项目。您将看到以下屏幕:如何操作…

  2. 选择创建一个简单项目(跳过存档选择)选项以避免选择要创建的内容。

  3. 在第一章的“使用 Maven 创建简单项目”菜谱中,填写我们指定的参数值,以创建一个简单的 Maven 项目。(组 ID:com.packt.cookbook存档 ID:simple-project)*如何操作…

  4. 点击完成。您的项目现在已设置完成。点击pom.xml文件。您将看到以下截图:如何操作…

它是如何工作的…

Eclipse 内置了对 Maven 项目的支持(使用m2e插件)。在本菜谱中,我们使用 Eclipse 创建了一个简单的 Maven 项目,跳过了存档选择。我们还指定了项目的groupIdartifactIdversion

使用这些信息,Eclipse 将调用 Maven 存档插件来创建一个快速启动项目。Eclipse 控制台显示了执行步骤,并创建了项目。

文件夹结构和内容与通过命令行创建的项目相同。

在 Eclipse 中导入现有的 Maven 项目

如果您已经通过命令行设置了 Maven 项目,那么它可以很容易地导入到 Eclipse 中。

如果您尚未设置 Eclipse 并验证 Maven 是否存在,请遵循前面菜谱中的准备就绪部分。

如何操作…

要在 Eclipse 中导入现有的 Maven 项目,请执行以下步骤:

  1. 导航到文件 | 导入…并点击Maven如何操作…

  2. 选择上一章中创建的项目:如何操作…

  3. 导入项目。您将看到的内容与我们创建新 Maven 项目时看到的内容相同。

它是如何工作的…

Eclipse 内置了对 Maven 项目的支持。当导入 Maven 项目时,它会解析指定项目的pom.xml文件。根据项目的 pom 配置文件,它创建相关的 Eclipse 配置以识别源文件、测试和存档。

它还会识别项目的所有依赖项,如果尚未下载,将使用 Maven 下载这些依赖项,并将它们添加到项目依赖项中。

在 NetBeans 中创建新的 Maven 项目

NetBeans 是另一个流行的 IDE。它由 Oracle 支持,功能丰富且可扩展,支持多种语言,如 Eclipse。

到目前为止,NetBeans 8.0.2 是最新的版本。本书中的截图反映了这个版本。

准备工作

如果尚未下载,NetBeans 可以通过两种不同的方式下载:

  • Oracle 提供了最新 JDK 和 NetBeans 最新版本的下载。这是一个不错的选择,尤其是如果你还没有安装 JDK。

  • 如果 JDK 已经安装,那么可以从 netbeans.org/ 独立下载 NetBeans。NetBeans 有不同的版本(类似于 Eclipse)。你可以根据自己的喜好选择 Java SE 或 Java EE,或者全部选择。

如何操作...

现在 NetBeans 已经安装,让我们通过以下步骤创建一个新的 Maven 项目:

  1. 导航到 工具 | 选项。选择 Java 并点击 Maven 选项卡。你会注意到 Maven Home 显示为 捆绑,版本为 3.0.5如何操作...

  2. 你可以保持原样,或者通过选择下拉菜单将其更改为你的 Maven 安装。

  3. 现在导航到 文件 | 新建项目

  4. 类别 中选择 Maven,从 项目 中选择 Java 应用程序,如图所示:如何操作...

  5. 指定项目的详细信息:如何操作...

你已经完成了!现在在 NetBeans 中创建了一个新项目。

它是如何工作的...

与 Eclipse 一样,NetBeans 内置了对 Maven 的支持。与 Eclipse 不同,NetBeans 并未使用 Maven 架构来快速启动。相反,它使用模板创建了一个新项目。在这种情况下,你会注意到它没有创建快速架构创建的虚拟源代码和测试类。

在 NetBeans 中导入现有的 Maven 项目

与前一个示例中创建新的 Maven 项目不同,你可能想要在 NetBeans 中打开一个现有的 Maven 项目。现在让我们看看如何导入一个现有的 Maven 项目。

准备工作

如果尚未下载,NetBeans 可以通过两种不同的方式下载:

  • Oracle 提供了最新 JDK 和 NetBeans 最新版本的下载。这是一个不错的选择,尤其是如果你还没有安装 JDK。

  • 如果 JDK 已经安装,那么可以从 netbeans.org/ 独立下载 NetBeans。NetBeans 有不同的版本(类似于 Eclipse)。你可以根据自己的喜好选择 Java SE 或 Java EE,或者全部选择。

如何操作...

要在 NetBeans 中导入现有的 Maven 项目,请执行以下步骤:

  1. 导航到 文件 | 打开项目...如何操作...

  2. 从命令行中选择我们之前创建的项目。注意 NetBeans 如何将其识别为 Maven 项目(带有 ma 图标):如何操作...

  3. NetBeans 现在打开了 Maven 项目。

工作原理...

与 Eclipse 一样,NetBeans 内置了对 Maven 的支持。它通过存在 pom.xml 文件识别一个文件夹为 Maven 项目。它解析此文件,并打开项目,将文件和文件夹关联到 源包依赖项项目文件,如下面的截图所示:

工作原理...

在 IntelliJ IDEA 中创建新的 Maven 项目

IntelliJ IDEA 是 JetBrains 的一个 IDE,它既有社区版也有商业版。IntelliJ IDEA 在开发者中非常受欢迎,并且定期更新最新的语言和平台功能。

为了本食谱的目的,我们将使用社区版。对于商业版,步骤也是相同的。

在撰写本书时,IntelliJ IDEA 14.0.3 是最新版本。本书中的截图反映了这个版本。

准备工作

由于 IntelliJ IDEA 需要 Java 环境来运行,让我们首先确保我们的系统上已设置 Java 环境:

  1. 确保已安装 JDK。

  2. 通过访问 www.jetbrains.com/idea/ 并点击 下载 链接来下载 IntelliJ IDEA。

  3. 确保项目 SDK 设置为您的 Java 安装。

如何操作...

使用以下步骤在 IntelliJ IDEA 中创建新的 Maven 项目:

  1. 打开 IntelliJ IDEA。

  2. 点击 创建新项目

  3. 选择 Maven

  4. 选择 从原型创建 选项,并选择 maven-archetype-quickstart:1.1如何操作...

  5. 指定创建项目所需的值:如何操作...

  6. 确认项目的值:如何操作...

你已经完成了!在 IntelliJ IDEA 中创建了一个新的 Maven 项目。

工作原理...

IntelliJ IDEA 对 Maven 提供了一级支持。它可以按照原型创建新的 Maven 项目,通过从仓库下载所需的插件和依赖项。它使用配置的 Maven 设置,这些设置可以在下一节中自定义。

更多内容...

您可以通过以下方式在 IntelliJ IDEA 中自定义 Maven:

  1. 导航到 配置 | 设置更多内容...

  2. 在左侧面板上点击 Maven更多内容...

  3. 点击 覆盖 以更改所需的值。

  4. 更改一些默认选项,例如 离线工作输出级别,如前一个截图所示。

在 IntelliJ IDEA 中导入现有的 Maven 项目

虽然我们可以使用 IntelliJ IDEA 创建新项目,但在大多数情况下,你已经在文件系统中有一个现有项目。在后一种情况下,你将想要导入此项目。

准备中

由于 IntelliJ IDEA 需要一个 Java 环境来运行,让我们首先确保我们的系统上已设置 Java 环境:

  1. 确保已安装 JDK。

  2. 通过访问 www.jetbrains.com/idea/ 并点击 下载 链接来下载 IntelliJ IDEA。

  3. 确保项目 SDK 设置为你的 Java 安装。

如何操作...

要在 IntelliJ IDEA 中导入现有的 Maven 项目,请执行以下步骤:

  1. 启动 IntelliJ IDEA。

  2. 选择 导入项目。浏览到我们之前创建的简单项目:如何操作...

  3. 如有需要,进行更改。更改可以按照以下截图所示进行:如何操作...

  4. 确认要导入的项目:如何操作...

完成了!现有的 Maven 项目现在已导入 IntelliJ IDEA。

它是如何工作的...

IntelliJ IDEA 对 Maven 提供了一级支持。它可以解析 pom 文件以确定项目结构和依赖关系,并在 IDE 中布局。

一旦项目在 IntelliJ IDEA 中打开,以下文件夹和文件将被创建:

它是如何工作的...

更多内容...

所有 Maven 相关操作都可以通过在 IntelliJ IDEA 中打开 Maven Projects 选项卡来执行:

更多内容...

你可以选择 生命周期 并点击要运行的阶段。例如,在先前的截图中,我们运行了 Lifecyclepackage 阶段。

第三章:Maven 生命周期

让我们开始使用 Maven。在本章中,我们将介绍以下食谱:

  • 理解 Maven 生命周期、阶段和目标

  • 理解 pom 文件

  • 理解 Maven 设置

  • 理解 Maven 的命令行选项

  • 理解 Maven 配置文件

  • 添加新的 Maven 配置文件

  • 激活/停用 Maven 配置文件

  • 在 Maven 中使用属性

  • 指定平台无关构建的源编码

简介

我们已经在我们的计算机上设置了 Maven。我们已经创建了一个简单的 Maven 项目并看到了如何构建它。我们还设置了 Maven 在我们首选的 IDE 上运行。

现在我们更好地理解 Maven 的工作原理以及如何使用它。我们将从理解 Maven 构建生命周期以及构成生命周期的阶段和目标开始。我们还将探索 Maven 的项目配置 pom 文件以及设置文件。我们还将尝试理解 Maven 配置文件是什么以及为什么需要它们。最后,我们将查看 Maven 的属性。

理解 Maven 生命周期、阶段和目标

当我们开始使用 Maven 时,我们需要了解 Maven 项目的生命周期。Maven 是基于构建生命周期的概念实现的。这意味着有一个明确的过程来使用 Maven 构建和分发工件。

生命周期由什么组成?生命周期的阶段被称为阶段。在每个阶段,可以执行一个或多个目标。

准备工作

Maven 已在您的系统上设置并验证其工作状态。有关设置 Apache Maven 的信息,请参阅第一章的前三个食谱,入门

如何做到这一点...

要构建一个 Maven 项目,请执行以下步骤:

  1. 打开命令提示符。

  2. 运行我们熟悉的 Maven 命令之一:

    mvn package
    
    
  3. 观察执行的各种步骤。

它是如何工作的...

Maven 有三个内置的构建生命周期:

  • defaultdefault 生命周期处理项目的构建和部署

  • cleanclean 生命周期清理 Maven 生成的文件和文件夹

  • sitesite 生命周期处理项目文档的创建

您会注意到您不必明确指定生命周期。相反,您指定的是阶段。Maven 根据指定的阶段推断生命周期。

例如,package 阶段表明它是 default 生命周期。

当 Maven 以 package 阶段作为参数运行时,将执行 default 构建生命周期。Maven 将按顺序运行所有阶段,直到并包括指定的阶段(在我们的例子中是 package 阶段)。

虽然每个生命周期都有多个阶段,但让我们看看每个生命周期的重要阶段:

  • clean 生命周期:clean 阶段会移除 Maven 在构建过程中创建的所有文件和文件夹

  • site 生命周期:site 阶段生成项目的文档,可以发布,以及可以进一步定制的模板

  • default 生命周期:以下是一些 default 生命周期的关键阶段:

    • validate:这个阶段验证所有项目信息是否可用且正确

    • process-resources:这个阶段将项目资源复制到目标位置以打包

    • compile:这个阶段编译源代码

    • test:这个阶段在合适的框架内运行单元测试

    • package:这个阶段将编译后的代码打包成其分发格式

    • integration-test:这个阶段在集成测试环境中处理包

    • verify:这个阶段运行检查以验证包是否有效

    • install:这个阶段将包安装到本地仓库

    • deploy:这个阶段将最终包安装到配置的仓库

每个阶段由插件目标组成。插件目标是一个构建项目的特定任务。一些目标只在特定阶段有意义(例如,Maven Compiler 插件的编译目标在编译阶段有意义,但 Maven Checkstyle 插件的 checkstyle 目标可以在任何阶段运行)。因此,一些目标绑定到生命周期的特定阶段,而其他则不是。

这里是一个阶段、插件和目标的表格:

阶段 插件 目标
clean Maven Clean 插件 clean
site Maven Site 插件 site
process-resources Maven Resources 插件 resource
compile Maven Compiler 插件 compile
test Maven Surefire 插件 test
package 根据打包方式而异;例如,Maven JAR 插件 jar(在 Maven JAR 插件的情况下)
install Maven Install 插件 install
deploy Maven Deploy 插件 deploy

理解 pom 文件

每个 Maven 项目都有一个 pom 文件,它定义了项目的内容以及如何构建它。Pom 是 项目对象模型 的缩写。让我们看看这个文件。

如何操作...

让我们通过以下步骤来理解 pom 文件:

  1. 前往我们在前几章中创建的 Maven 项目。

  2. 打开名为 pom.xml 的文件。

它是如何工作的...

pom 文件是一个基于特定架构的 XML 文件,如文件顶部所指定的:

<project 

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">

此外,还有一个 modelVersion 元素,它定义了此架构的版本:

<modelVersion>4.0.0</modelVersion>

这些是 pom 文件的基本元素。

groupId 元素是项目所属组织的唯一标识符。对于我们的示例项目,它是 org.packt.cookbook。遵循反向域名表示法来指定这是一个好习惯:

<groupId>...</groupId>

artifactId 元素是项目的名称。对于我们的示例项目,它是 simple-project

<artifactId>...</artifactId>

version 元素是项目的特定实例,对应于特定时间点的源代码。在我们的例子中,它是 1.0-SNAPSHOT,这是开发期间的一个默认版本:

<version>...</version>

我们将在本书的后面部分探讨 SNAPSHOT 版本和具体版本之间的区别。

groupIdartifactIdversion的组合唯一标识项目。从这个意义上讲,它们是项目的坐标。

packaging元素表示项目的工件类型。这通常是jarwarzip,在某些情况下,是pom

  <packaging>...</packaging>

pom 文件中的dependencies元素部分定义了此项目的所有依赖项目。这通常是需要构建、测试和运行项目的第三方库:

  <dependencies>...</dependencies>

parent部分用于表示关系,具体来说是父子关系。如果项目是多模块项目的一部分或从另一个项目继承项目信息,那么详细信息将在此部分中指定:

  <parent>...</parent>

Maven 属性是占位符。它们的值可以通过使用${key}在任何 pom 文件位置访问,其中key是属性名称:

  <properties>...</properties>

拥有模块的项目被称为多模块或聚合项目。模块是 pom 文件中列出的项目,并且作为一个组执行:

  <modules>...</modules>

有关多模块项目的更多信息,请参阅第九章,多模块项目

理解 Maven 设置

现在我们已经了解了 pom 文件的基本元素,让我们也来检查 Maven 的各种设置属性。

如何操作...

要了解 Maven 设置,请执行以下步骤:

  1. 如果存在,打开您的HOME文件夹的.m2子文件夹中的settings.xml文件:如何操作...

  2. 否则,打开 Maven 安装目录下的conf文件夹中的settings.xml文件(如M2_HOME中定义的)。

它是如何工作的...

Maven 有一个全局设置文件,名为settings.xml,位于 Maven 安装目录的conf文件夹中。此文件中的值可以在用户设置文件中覆盖——存在于您的HOME文件夹.m2子文件夹中的settings.xml文件。

设置文件包含不是特定于项目的配置,而是具有全局性质。它还包含不打算分发的信息(例如,密码)。

与 pom 文件一样,设置文件也是一个基于 XML 模式的 XML 文件。它以以下方式开始:

<settings 

      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          http://maven.apache.org/xsd/settings-1.0.0.xsd">

现在我们来看一些典型的设置配置:

localRepository元素

以下代码表示设置文件中的localRepository元素:

<localRepository>${user.home}/.m2/repository</localRepository>

我们在第一章中看到的Changing the location of the Maven repository配方中已经看到了这一点,我们想要更改 Maven 依赖项和插件存储的默认位置。

离线元素

以下代码表示设置文件中的offline元素:

<offline>false</offline>

此设置指示 Maven 是否应在离线模式下运行;也就是说,如果不可用,则不应下载更新或依赖项。

代理元素

我们在 第一章 的“在 HTTP 代理服务器后面运行 Maven”配方中看到了代理。以下代码表示设置文件中的 proxies 元素:

<proxies>
    <proxy>
      <id>myproxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.myorg.com</host>
      <port>8080</port>
      <username>proxyuser</username>
      <password>somepassword</password>
      <nonProxyHosts>*.myorg.com </nonProxyHosts>
    </proxy>
  </proxies>

这允许我们指定一个代理服务器以连接到互联网。这在由于安全或其他原因可能阻止直接访问互联网的企业中是相关的。

镜像元素

以下代码表示设置文件中的 mirrors 元素:

   <mirror>
      <id>nexus</id>
      <name>My Company Mirror</name>
      <url>http://nexus.mycompany.com/pub/maven2</url>
      <mirrorOf>central</mirrorOf>
    </mirror>

与从 Maven Central 下载依赖项相比,您可以配置 Maven 从中央仓库的镜像下载依赖项。这在仓库可以在组织内部的仓库管理器中镜像,并且所有用户都可以从这个镜像下载依赖项的组织中非常有用。

仓库元素

仓库是 Maven 用于将所需的依赖项填充到本地仓库的远程项目集合。有两种类型的仓库——“发布”和“快照”——Maven 允许为每个仓库进行特定配置,如下面的代码所示:

<repositories>
        <repository>
          <id>codehausSnapshots</id>
          <name>Codehaus Snapshots</name>
          <releases>
            <enabled>false</enabled>
            <updatePolicy>always</updatePolicy>
            <checksumPolicy>warn</checksumPolicy>
          </releases>
          <snapshots>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
            <checksumPolicy>fail</checksumPolicy>
          </snapshots>
          <url>http://snapshots.maven.codehaus.org/maven2</url>
          <layout>default</layout>
        </repository>
      </repositories>

插件仓库元素

虽然“仓库”存储项目所需的依赖项,但pluginRepositories元素存储插件库和相关文件。Maven 通过为这两个元素提供单独的配置来区分它们。这些元素与仓库的元素相同,只是父元素是 pluginRepositories

服务器元素

下载和部署的仓库由 pom 文件中的 repositoriesdistributionManagement 元素定义。然而,出于保密原因,如 usernamepassword 这样的设置不能在 pom 文件中分发。Maven 提供了一种机制,可以在设置文件中指定这些设置:

<servers>
    <server>
      <id>server001</id>
      <username>my_login</username>
      <password>my_password</password>
      <privateKey>${user.home}/.ssh/id_dsa</privateKey>
      <passphrase>some_passphrase</passphrase>
      <filePermissions>664</filePermissions>
      <directoryPermissions>775</directoryPermissions>
      <configuration></configuration>
    </server>
  </servers>

理解 Maven 的命令行选项

虽然指定目标是最流行的运行 Maven 的方式,但 Maven 提供了许多命令行选项来自定义其行为。这些选项从指定属性的值到改变 Maven 输出的详细程度不等。了解一些参数是有用的,因为它们通常会帮助解决与 Maven 相关的问题。

准备工作

Maven 已在您的系统上设置并验证其工作状态。

如何操作...

要理解 Maven 的命令行选项,请执行以下步骤:

  1. 打开命令提示符。

  2. 运行以下命令:

    mvn –h
    
    
  3. 您将看到如下截图所示的输出:如何操作...

Maven 支持的许多选项在上面的屏幕截图中显示。

它是如何工作的...

我们将简要讨论 Maven 提供的命令行选项。

选项

当运行 Maven 时出现错误,此标志将导致 Maven 显示错误详细堆栈跟踪:

-e –errors

当启用quiet选项时,只显示错误。其他输出不会打印。这允许加快构建速度,因为在通常显示详细输出的情况下:

-q –quiet

我们在第一章的“入门”的前三个菜谱中看到了version选项,用于显示 Maven 版本。这也是检查 Maven 是否已安装并正常工作的简单方法:

-v –version

当使用offline选项调用时,Maven 不会尝试从互联网下载任何依赖或插件。此选项将正确工作,前提是 Maven 拥有构建和运行项目所需的所有信息。我们将看到如何启用项目以离线模式运行:

-o –offline

当启用debug选项时,Maven 会打印出关于它执行的每个步骤的大量详细输出。这通常用于解决任何构建问题:

-X –debug

理解 Maven 配置文件

Maven 旨在创建可移植的构建,预期将在不同的平台和不同的运行时环境中工作。

现在,可能存在需要以不同方式构建相同项目的情况。例如,您可能需要为预演和生产目的以不同的方式构建项目。您可能不希望在 Windows 上构建需要 Linux 库的项目。

如何操作...

通过以下步骤来理解 Maven 配置文件:

  1. 在您的 Maven 安装的conf子文件夹中打开settings.xml(如M2_HOME中指定)。

  2. 查看配置文件中的注释部分。

它是如何工作的...

Maven 提供了三种类型的配置文件:

  • 根据项目 pom 文件定义的项目配置文件

  • 根据用户设置文件(位于用户HOME文件夹的.m2子文件夹中)定义的用户配置文件

  • 一个全局配置文件,如全局设置文件(位于M2_HOMEconf文件夹中)定义

通过为项目构建的不同变体创建不同的配置文件,您可以使用相同的 pom 文件创建不同的构建。

应小心确保这不会导致不可移植的构建。

添加新的 Maven 配置文件

让我们添加一个简单的 Maven 配置文件来测试我们对配置文件的理解。

如何操作...

让我们通过以下步骤创建一个新的 Maven 配置文件:

  1. 使用第一章中“使用 Maven 创建简单项目”菜谱中指定的命令创建一个新的 Maven 项目。

  2. pom.xml文件中添加以下代码:

    <profiles>
          <profile>
              <id>dev</id>
              <activation>
                  <activeByDefault>false</activeByDefault>
              </activation>
          </profile>
      </profiles>
    

它是如何工作的...

创建配置文件有两种方式:在项目的 pom 文件中或在设置文件中。重要的是要注意,如果配置文件从设置文件中激活,其值将覆盖 pom 文件中具有等效 ID 的任何配置文件。

pom.xml中的配置文件可以包含以下元素:

<profile>
      <id>test</id>
      <activation>...</activation>
      <build>...</build>
      <modules>...</modules>
      <repositories>...</repositories>
      <pluginRepositories>...</pluginRepositories>
      <dependencies>...</dependencies>
      <reporting>...</reporting>
      <dependencyManagement>...</dependencyManagement>
      <distributionManagement>...</distributionManagement>
    </profile>

settings.xml中的配置文件只能包含以下元素:

<profile>
      <id>test</id>
      <activation>...</activation>
      <repositories>...</repositories>
      <pluginRepositories>...</pluginRepositories>
      <properties>…</properties>
      </profile>

参见

  • 本章中的激活/停用 Maven 配置文件菜谱

激活/停用 Maven 配置文件

配置文件可以在 pom.xmlsettings.xml 中指定。每个配置文件可能都是为了特定目的而创建的;例如,在特定平台上运行或在集成环境中运行。并非所有配置文件在所有情况下都需要运行。Maven 提供了一种机制,根据需要激活和禁用配置文件。

准备工作

使用我们创建配置文件的项目来添加一个新的 Maven 配置文件部分。

如何操作...

让我们执行以下步骤来激活/禁用 Maven 配置文件:

  1. 要禁用配置文件,在 activeByDefault 元素中设置以下值:

    <activeByDefault>false</activeByDefault>
    
  2. 运行 Maven 命令以检查配置文件是否激活:

    mvn help:active-profiles
    
    

    前一个命令的输出如下所示:

    [INFO] --- maven-help-plugin:2.2:active-profiles (default-cli) @ project-with-profile ---
    [INFO]
    Active Profiles for Project 'com.packt.cookbook:project-with-profile:jar:1.0-SNAPSHOT':
    The following profiles are active:
    
    
  3. 要激活配置文件,设置以下值:

    <activeByDefault>true</activeByDefault>
    
  4. 通过执行以下命令来确认配置文件现在已激活:

    mvn help:active-profiles
    
    

    前一个命令的输出如下所示:

    The following profiles are active:
    - dev (source: com.packt.cookbook:project-with-profile:1.0-SNAPSHOT)
    
    

它是如何工作的...

配置文件可以通过以下方式之一被触发:

  • 明确:在这里,Maven 提供了一个命令行选项来调用配置文件,如下所示命令:

    mvn –P dev package
    
    

    这将调用 dev 配置文件

  • 通过设置:可以通过将 <active> 属性设置为 true 在设置文件中激活配置文件。如果激活,当项目构建时,将调用配置文件:

      <activeProfiles>
        <activeProfile>dev</activeProfile>
      </activeProfiles>
    
  • 基于环境变量:配置文件可以根据任何环境变量及其值被激活:

    <profile>
        <activation>
          <property>
            <name>debug</name>
          </property>
        </activation>
        ...
    </profile>
    

    如果系统属性 debug 被定义并且有任意值,则配置文件将被激活

  • 根据操作系统设置:以下配置文件仅在 Windows 上运行:

    <profile>
        <activation>
          <os>
            <family>Windows</family>
          </os>
        </activation>
        ...
      </profile>
    
  • 存在或缺失的文件:如果 target/site 文件缺失,以下配置文件将被激活:

    <profile>
        <activation>
          <file>
            <missing>target/site</missing>
          </file>
        </activation>
      </profile>
    

在 Maven 中使用属性

Maven 允许我们定义和使用属性。属性允许我们在多个地方避免硬编码值,例如依赖项的版本。它们还通过允许在运行时传递值来为构建工具提供灵活性。

如何操作...

让我们通过以下步骤定义和使用 Maven 属性:

  1. 打开我们之前创建的项目 pom 文件。

  2. 定义一个属性:

    <properties>
        <junit.version>3.8.1</junit.version>
    </properties>
    
  3. 使用属性:

    <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>${junit.version}</version>
          <scope>test</scope>
        </dependency>
    

它是如何工作的...

属性有不同类型。如下所示:

  • 环境变量:在变量前加上 env. 将返回 shell 环境变量的值。例如,${env.PATH} 将返回 PATH 变量的值。

  • pom 变量:在变量前加上 project. 将返回 pom 文件中该元素的值。例如,${project.version} 将返回 pom 文件 <version> 标签中的值。

  • settings 变量:在变量前加上 settings. 将返回设置文件中该元素的值。例如,${settings.offline} 将返回设置文件中的 <offline> 值。

  • Java 属性:Java 中的 System.getProperties() 方法可用的任何属性都可用。例如,${java.home}

  • 正常属性:在<properties>标签中指定的值,如下例所示:

    <properties>
      <java.version>1.7</java.version>
    </properties>
    

    这里,${java.version}命令将返回1.7

记住,属性和配置文件可能会破坏项目的可移植性。以下是在问题区域查找的两个具体做法:

  • 外部属性:这些是在 pom 文件外部(在设置文件中)定义的属性,但作为插件配置的一部分使用。缺少此属性定义将破坏构建。

  • 不完整的指定:这是为不同的构建环境定义属性的地方。对于其中一个缺少定义将破坏构建。

参见

  • 本章中的为平台无关构建指定源编码配方。

为平台无关构建指定源编码

让我们把对属性的学习应用到实践中。你可能会在构建我们在第一章中创建的简单项目时观察到以下警告,该项目是在Maven 构建简单项目的配方中介绍的,入门

[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources,
i.e. build is platform dependent!

如果我们真的不希望构建依赖于平台,就让我们移除这个警告。

如何操作...

让我们在 Maven 项目中通过以下步骤指定平台无关构建的源编码:

  1. 打开我们之前创建的 pom 文件。

  2. 添加以下代码:

    <properties>
          <project.build.sourceEncoding>UTF-8 </project.build.sourceEncoding>
      </properties>
    
  3. 运行以下命令:

    mvn package
    
    
  4. 观察到警告不再存在。

它是如何工作的...

project.build.sourceEncoding属性明确指定了源文件的编码。Maven 插件从该属性的值获取编码信息并使用它。

这个值将在项目构建的任何平台上都是相同的,因此构建变得与平台无关。

第四章. 必要的 Maven 插件

在本章中,我们将探讨以下食谱:

  • 使用 Maven Clean 插件

  • 使用 Maven 编译器插件

  • 更改 Maven 编译器插件使用的编译器

  • 为编译器插件指定 Java 版本

  • 使用 Maven Surefire 插件运行单元测试

  • 使用 Maven Failsafe 插件运行集成测试

  • 使用 Maven 资源插件

  • 使用资源进行过滤

  • 使用 Eclipse 运行 Maven 目标

  • 使用 NetBeans 运行 Maven 目标

  • 使用 IntelliJ IDEA 运行 Maven 目标

简介

在上一章中,我们学习了 Maven 生命周期及其阶段和目标,了解了 pom 项目配置文件和设置文件的基本元素,并学习了如何使用 Maven 配置文件和属性。

在本章中,我们将探讨如何向 pom 文件添加和配置插件,并使用它们来执行基本构建任务。Maven 具有插件架构,除了核心功能外,Maven 中的每个任务都是通过插件完成的。Maven 提供了大量的插件。此外,还有几个第三方插件。如果用户选择这样做,Maven 还提供了一种机制,让用户开发自己的插件。

使用 Maven Clean 插件

当项目构建时,确保它不会被早期构建的工件所不利影响是很重要的。通常,构建工具在定义良好的文件夹中生成工件,即 target 文件夹,称为项目工作目录。在新构建之前,这个文件夹通常会被删除。

准备工作

Maven 已在您的系统上设置并验证其工作。要这样做,请参考 第一章 入门 的前三道食谱。

如何操作...

让我们通过以下步骤开始使用 Maven Clean 插件:

  1. 打开命令提示符。

  2. 在我们创建的简单 Maven 项目中运行以下 Maven 命令,该命令位于 第一章 中 使用 Maven 创建简单项目 的食谱中:入门

    mvn clean
    
  3. 观察执行的各种步骤:

    [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ simple-project ---
    [INFO] Deleting C:\projects\apache-maven-cookbook\simple-project\target
    
    

    如果没有文件/文件夹要删除,您将看不到以下输出:

    [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ simple-project ---
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    
    

它是如何工作的...

当调用 clean 阶段时,Maven 会自动推断出正在调用 clean 生命周期。

它使用 Maven Clean 插件来完成这项工作。该插件只有一个目标,即 clean,用于清理工作目录。

在 Maven 的情况下,工作目录被称为 target。Maven 在构建完成后创建此目录。插件的 clean 目标尝试删除此目录。

由于 clean 是一个与 default(构建)生命周期分开的生命周期,如果你需要确保工作目录被删除,那么在 default 生命周期之前需要显式调用 clean

更多...

在本节中,我们将讨论如何在构建过程中自动运行 Clean 插件,跳过删除工作目录的步骤,以及删除一些额外文件/文件夹的过程。

自动清理

在前面的例子中,因为我们使用了插件的默认行为,并且不需要进行任何配置,所以我们不需要对 pom 配置文件进行任何更改。然而,如果我们想确保clean目标在没有明确调用的情况下运行,该怎么办?

要做到这一点,我们需要在我们的 pom 文件中定义带有一些参数的插件:

  1. 让我们在 pom 文件中添加以下代码:

        <build>
            <plugins>
              <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.6</version>
                <executions>
                  <execution>
                    <id>auto-clean</id>
                    <phase>initialize</phase>
                    <goals>
                      <goal>clean</goal>
                    </goals>
                  </execution>
                </executions>
              </plugin>
            </plugins>
          </build>
    

    尽管前面的声明可能看起来很冗长,但我们只是要求在项目的initialize阶段调用clean目标。我们使用一个名为auto-cleanid来标识这个execution

  2. 现在在命令提示符上运行以下命令:

    mvn package
    
    
  3. 你将看到以下截图:自动清理

即使我们没有调用clean阶段,由于在 pom 文件中配置了在initialize阶段运行,clean目标仍然被触发。

跳过删除工作目录

让我们看看前面用例的反面。由于某种原因,我们不想删除工作目录,即使运行了clean。为此,请执行以下步骤:

  1. 按照以下方式配置插件:

        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>2.6</version>
          <configuration>
            <skip>true</skip>
          </configuration>
        </plugin>
    
  2. 在命令提示符上运行以下命令:

    mvn clean
    
    
  3. 观察以下输出:

    C:\projects\apache-maven-cookbook\project-with-clean-disabled>mvn clean
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Project with clean disabled 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-clean-plugin:2.6:clean (default-clean) @ project-with-clean-disabled ---
    [INFO] Clean is skipped.
    
    

skip插件属性设置为true表示告诉 Maven 必须跳过clean目标。

删除额外的文件夹/文件

如果你的项目除了target之外还有一个额外的文件夹,比如report,这可能是由另一个脚本创建的,并且你希望也删除它?我们使用以下步骤来完成同样的操作:

  1. 按照以下方式配置插件:

      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <filesets>
            <fileset>
              <directory>${basedir}/report</directory>
            </fileset>
          </filesets>
        </configuration>
      </plugin>
    

    你现在已经配置了插件来删除一个额外的目录

  2. 创建一个report文件夹用于测试。

  3. 在命令提示符上运行以下命令:

    mvn clean
    
    
  4. 你现在将看到以下输出:

    C:\projects\apache-maven-cookbook\project-with-clean-additional-folder>mvn clean
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Project with clean additional folder 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-clean-plugin:2.6:clean (default-clean) @ project-with-clean-additional-folder ---
    [INFO] Deleting C:\projects\apache-maven-cookbook\project-with-clean-additional-folder\report (includes = [], excludes = [])
    
    

report文件夹也被删除了。实际上,Maven 可以被配置为删除(或不清除)该文件夹内的特定文件夹和文件。

使用 Maven 编译器插件

编译是构建工具执行的基本任务之一。Maven 使用 Maven 编译器插件来进行编译。该插件提供了一些配置选项,使编译更加灵活。

如何操作...

要使用 Maven 编译器插件,请执行以下步骤:

  1. 打开命令提示符。

  2. 在第一章中,按照使用 Maven 创建简单项目的步骤创建的简单项目中运行以下 Maven 命令:

    mvn compile
    
    
  3. 观察以下输出:

    [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ simple-project ---
    [INFO] Compiling 1 source file to C:\projects\apache-maven-cookbook\simple-project\target\classes
    
    

它是如何工作的...

compile参数表示对 Maven 的default生命周期的调用。如第三章中理解 Maven 生命周期、阶段和目标配方所示,Maven 按顺序运行所有阶段,包括compile阶段。

compile阶段本身实际上是在运行 Maven Compiler 插件的compile目标。

这将 Java 源文件编译成target/classes文件夹中的类。

一个问题可能会让你感到困惑。关于测试类呢?为什么compile阶段不编译测试源文件?

答案在于 Maven 处理生命周期和生命周期阶段的方式。除非你想运行测试,否则你为什么要编译测试源文件?

更多...

如果我们想要编译测试源文件怎么办?

让我们在命令提示符上尝试运行以下命令:

mvn test

观察以下截图所示的输出:

更多...

由于我们指定了test阶段,Maven 运行了它之前的所有阶段,包括使用 Maven Compiler 插件的testCompile目标编译测试源文件。

更改 Maven Compiler 插件使用的编译器

假设我们正在使用 JDK 7 运行 Maven,但我们的项目需要使用 JDK 8 编译源文件。本质上,我们想要使用一个与运行 Maven 的 JDK 不同的 JDK 进行编译。

在这种情况下,我们可以指定我们想要用于 Maven 的编译器。

如何操作...

使用以下步骤更改 Maven Compiler 插件使用的编译器:

  1. 打开命令提示符。

  2. 定义一个 Maven 属性以存储 Java 8 的位置详细信息:

    <properties>
        <JAVA8.HOME>C:/Program Files/Java/jdk1.8.0_20</JAVA8.HOME>
    </properties>
    

    注意

    要以便携的方式完成此操作,可以在用户的settings.xml文件中的profile中定义此属性。这是因为JAVA_HOME的位置可能因用户的操作系统或首选安装位置而不同。

  3. 将以下插件配置添加到 Maven 项目中:

        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
              <verbose>true</verbose>
              <fork>true</fork>
              <executable>${JAVA8.HOME}/bin/javac</executable>
              <compilerVersion>1.8</compilerVersion>
            </configuration>
          </plugin>
        </plugins>
    

    注意

    为了使前面的代码生效,fork元素需要设置为true。Maven 将在单独的线程中调用不同的 Java 编译器,因此需要分叉。这样做是为了让 Maven 能够加载与不同 JDK 对应的不同的 JVM。

  4. 在命令提示符上运行以下命令:

    mvn compile
    
    

它是如何工作的...

编译发生的方式不会有明显的区别,除了现在,executable元素中指定的编译器将被调用。

参见

  • 本章中指定编译器插件的 Java 版本配方

指定编译器插件的 Java 版本

当我们在 Eclipse 中创建新项目时,你会观察到以下警告:

指定编译器插件的 Java 版本

为什么会出现这个错误?这是因为 Maven Compiler 插件默认将sourcetarget Java 版本视为1.5(出于向后兼容性原因)。

让我们解决这个问题警告。

如何做到这一点...

假设你已经在 Eclipse 中将 Java 8 配置为默认的 Java 运行时,并执行以下步骤:

  1. 打开 Eclipse 项目。

  2. 将以下配置添加到 Maven Compiler 插件中:

        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
    
  3. 或者,在 properties 元素中添加以下属性(这实际上是前面过程的快捷方式):

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>
    
  4. 检查警告是否消失。

它是如何工作的...

sourcetarget 版本的 Java 明确设置到编译器时,源代码中使用的 Java 版本以及编译类所期望的版本是明确的。编译器编译到错误的 Java 目标版本的可能性很小。

因此,Eclipse 警告消失了。

更多...

你可能需要在 compilerArguement 元素中传递编译器参数。例如,你可能想识别代码中已弃用的 API 的使用。你可以通过添加以下配置来完成此操作:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.2</version>
    <configuration>
       <compilerArgument>-Xlint:deprecation</compilerArgument>
    </configuration>
</plugin>

当在具有弃用代码上运行时,你可以看到相关的行:

[INFO] Compiling 1 source file to C:\projects\apache-maven-cookbook\project-with-deprecation\target\classes
[WARNING] /C:/projects/apache-maven-cookbook/project-with-deprecation/src/main/java/com/packt/cookbook/App.java:[12,24] Date(int,int,int) in java.util.Date has been deprecated

使用 Maven Surefire 插件运行单元测试

软件开发的最佳实践之一是为你开发的代码编写自动化单元测试。现在让我们看看如何运行这些测试。

执行此任务的插件是 Maven Surefire 插件。

如何做到这一点...

要使用 Maven Surefire 插件运行单元测试,请执行以下步骤:

  1. 打开命令提示符。

  2. 在我们的一个示例项目中运行以下命令:

    mvn test
    
    
  3. 观察执行的各种步骤:

    [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ simple-project ---
    [INFO] Surefire report directory: C:\projects\apache-maven-cookbook\simple-project\target\surefire-reports
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running com.packt.cookbook.AppTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
    Results:
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    

它是如何工作的...

test 参数表示对 Maven 的 default 生命周期的调用。如第三章中“理解 Maven 生命周期、阶段和目标”配方所示,Maven 按顺序运行所有阶段,包括 test 阶段。

test 阶段本身实际上运行了 Maven Surefire 插件的 test 目标。

这将运行 target/test-classes 文件夹中存在的测试类。

我们拥有的测试是使用 JUnit 框架编写的测试。插件不仅运行测试,还生成可以用来分析失败以及测试覆盖率的测试报告。

检查 surefire-reports 文件夹:

它是如何工作的...

虽然文本文件包含总结报告,但 XML 文件包含每个测试的详细信息。

更多...

Surefire 插件提供了许多配置,以使测试更容易。

使用 TestNG

JUnit 并非编写自动化单元测试的唯一方式。你可以使用 TestNG (testng.org) 或者甚至在不使用任何框架的情况下(通过使用 Java 断言)编写测试。

Surefire 根据已定义的依赖项确定要使用的框架。

我们之前的例子运行了 JUnit 测试,因为我们已经在 pom 文件中定义了 junit 依赖。

现在,让我们使用 TestNG 编写一个测试,看看需要更改什么才能使其工作。参考带有 TestNG 的 Maven 项目。

pom 文件中唯一的更改是将junit依赖项替换为testng

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.8.8</version>
    <scope>test</scope>
</dependency>

在命令提示符下运行以下命令:

mvn test

现在测试将使用 TestNG 运行:

[INFO]
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ project-with-testNG---
[INFO] Surefire report directory: C:\projects\apache-maven-cookbook\project-with-testNG\target\surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.packt.cookbook.AppTest
Set up run
Fast test
Slow test
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.609 sec

现在,检查surefire-reports文件夹。它包含与testng对应的不同文件集:

使用 TestNG

与 TestNG 和 JUnit 一样,相同的测试可以在 TestNG 中运行。

跳过测试

可能存在你不想运行测试的情况;一些测试可能已损坏。可以通过以下方式完成:

  • 在 pom 文件中配置 Surefire 插件:使用以下代码在 pom.xml 文件中配置你的 Surefire 插件:

        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.17</version>
            <configuration>
              <skipTests>true</skipTests>
            </configuration>
          </plugin>
        </plugins>
    

    现在,运行以下命令:

    mvn test
    
    

    你将看到以下输出:

    [INFO]
    [INFO] --- maven-surefire-plugin:2.17:test (default-test) @ project-with-tests-skipped ---
    [INFO] Tests are skipped.
    
    
  • 通过命令行参数发出mvn命令:即使发出以下命令,也可以跳过测试:

    mvn –DskipTests tests
    
    

跳过测试源的编译

在前面的 mvn 命令中使用的skipTests参数跳过了测试的运行,但测试源仍然由早期阶段/目标编译。要跳过测试源的编译,你可以运行以下命令:

mvn –Dmaven.test.skip=true package

这将完全跳过测试编译和测试执行。

使用 Maven Failsafe 插件运行集成测试

除了单元测试外,Maven 还允许你自动化运行你的集成测试。虽然单元测试在构建生命周期的test阶段运行,但集成测试在verify阶段运行。Maven Failsafe 插件用于运行集成测试。

如何做...

要使用 Maven Failsafe 插件运行集成测试,请执行以下步骤:

  1. 打开包含集成测试的项目,即project-with-integration-test

  2. 将以下插件配置添加到 pom 文件中:

    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-failsafe-plugin</artifactId>
       <version>2.18</version>
       <executions>
          <execution>
            <id>integration-tests</id>
            <goals>
               <goal>integration-test</goal>
               <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    
  3. 运行以下命令:

    mvn verify
    
    
  4. 观察执行的各种步骤:如何做...

它是如何工作的...

我们在 pom 文件中指定了集成测试必须运行,以及 Maven Failsafe 插件的目的是必须验证。这些目标绑定到 Maven 的verify阶段,并会被调用。

使用 Maven Resources 插件

资源插件出现以将项目资源复制到输出目录。资源可以是项目运行或测试的目的。

如何做...

让我们通过以下步骤开始使用 Maven Resources 插件:

  1. 打开命令提示符。

  2. 在我们之前创建的简单项目中运行以下命令:

    mvn process-resources
    
    
  3. 观察以下情况:

    [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ simple-project ---
    [INFO] skip non existing resourceDirectory C:\projects\apache-maven-cookbook\simple-project\src\main\resources
    
    

它是如何工作的...

当我们指定process-resources阶段时,Maven 执行maven-resources-pluginresources目标,该目标绑定到process-resources生命周期阶段。

在早期项目中,没有资源,因此资源不会被复制。

如果你向 src\main\resources 目录中添加一个文件(例如 project-with-resources 项目的情况),你将看到以下输出:

[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ project-with-properties ---
[INFO] Copying 1 resource

你也可以显式调用插件的 goal,如下所示:

mvn resources:resources

你也可以调用 process-resources 阶段之后的任何阶段,这将触发资源处理:

mvn compile

有一个单独的目标用于将测试资源复制到提供主资源和测试资源分离的地方。像项目资源一样,测试资源处理可以通过以下三种方式之一调用,如下所示:

  • 通过指定一个将自动调用其之前阶段的阶段:

    mvn process-test-resources
    
    
  • 通过显式声明插件的目标:

    mvn resources:testResources
    
    
  • 通过跟随 process-test-resources 的阶段:

    mvn test
    
    

还有更多...

如果我们在额外的文件夹中有资源怎么办?Maven 资源插件允许我们配置这些额外的文件夹。

假设我们有一个额外的资源文件夹,即 src/main/additional。我们可以按照以下方式配置 pom.xml 文件:

<build>
   <resources>
     <resource>
         <directory>src/main/resources</directory>
     </resource>
     <resource>
         <directory>src/main/additional</directory>
     </resource>
   </resources>
   </build>

现在,运行以下命令:

mvn process-resources

观察输出:

[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ project-with-additional-resources ---
[INFO] Copying 1 resource
[INFO] Copying 1 resource

线 Copying 1 resource 重复两次,表明从两个文件夹中发生了复制。

使用资源进行过滤

现在,让我们看看我们如何将 Maven 的资源功能用于良好,即对项目资源执行变量替换。这个特性在你需要根据部署平台使用不同的配置值参数化构建时很有用。

你可以在你的资源中定义变量。让我们看看我们如何从属性、资源过滤器文件和命令行中获取这些变量的值。

如何做到这一点...

要使用资源进行过滤,请按照以下步骤操作:

  1. src/main/resource/app.properties 文件中添加一个带有变量的属性:

    display.name=Hello ${project.name}
    
  2. 在 pom 文件中添加以下代码:

      <build>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
          </resource>
        </resources>
      </build>
    
  3. 调用 process-resources 阶段:

    mvn process-resources
    
    
  4. 检查 target/classes 中的处理后的资源 app.properties

    C:\projects\apache-maven-cookbook\project-with-resource-filtering\target\classes>type app.properties
    display.name=Hello Project with resource filtering
    
    

它是如何工作的...

在 第三章 的 Maven 生命周期使用 Maven 中的属性 菜谱中,我们看到了 Maven 可以拥有的各种属性类型。在前面的例子中,我们将 filtering 元素设置为 true。Maven 将变量 ${project.name} 替换为在 pom 文件中定义的项目名称对应的属性值,即 Project with resource filtering

还有更多...

你可以从命令行覆盖属性值:

mvn –Dproject.name="Override from command line" process-resources

现在,通过导航到 target/classes 查看 app.properties

C:\projects\apache-maven-cookbook\project-with-resource-filtering>type target\classes\app.properties
display.name=Hello Override from command line

如果你有很多变量,它们的值根据环境而不同,那么你可以在项目代码库中创建一个文件,例如 my-filter-values.properties,在其中持有键和值(例如,src/filter 文件夹),并将它们用作过滤器:

<filters>
    <filter>my-filter-values.properties</filter>
</filters>

使用 Eclipse 运行 Maven 目标

如果你正在使用 Eclipse 开发你的项目,了解如何使用 IDE 运行我们之前讨论的一些插件是很有帮助的。

如何做到这一点...

要使用 Eclipse 运行 Maven 目标,请按照以下步骤操作:

  1. 在 Eclipse 中打开简单项目。

  2. 右键单击项目。

  3. 选择运行方式

  4. 查看可用的 Maven 选项:如何操作...

如何工作...

Eclipse 提供了一个选项,可以从 IDE 中运行各种目标。在我们本章中看到的目标中,cleancompiletest由 Eclipse 提供。还有一些其他选项。

此外,Eclipse 还允许我们根据需要修改配置。

Eclipse 还允许项目以传统方式(不使用任何 Maven 插件)作为 Java 应用程序运行。同样,它允许在没有使用 Maven 的情况下运行JUnit 测试

使用 NetBeans 运行 Maven 目标

现在我们来看看如何在 NetBeans 中运行 Maven 目标。

如何操作...

要使用 NetBeans IDE 运行 Maven 目标,请执行以下步骤:

  1. 在 NetBeans IDE 中打开简单项目。

  2. 右键单击项目。

  3. 查看可用选项:如何操作...

如何工作...

与 Eclipse 不同,NetBeans 具有更紧密的 Maven 集成。这意味着每个菜单选项(构建清理和构建清理等)都会调用相应的 Maven 命令来执行。

例如,单击清理选项将产生以下结果:

如何工作...

如所示,它运行了mvn clean命令。

同样,清理和构建选项等同于mvn clean install命令。

这些是简单的用例。NetBeans 提供了额外的配置选项来覆盖默认的 Maven 行为。

使用 IntelliJ IDEA 运行 Maven 目标

最后,让我们看看 IntelliJ IDEA 提供了什么。

如何操作...

要使用 IntelliJ IDEA 运行 Maven 目标,请执行以下步骤:

  1. 在 IntelliJ IDEA 中打开简单项目。

  2. 选择Maven 项目如何操作...

  3. 打开生命周期并单击一个合适的目标/阶段:如何操作...

如何工作...

单击 Maven 阶段/目标将调用相应的 Maven 命令并执行。例如,单击编译将执行以下操作:

如何工作...

IntelliJ IDEA 还提供了其他配置选项,用于自定义 Maven 项目。

第五章. 依赖管理

在本章中,我们将介绍以下食谱:

  • 选择依赖的范围

  • 获取依赖报告

  • 进入依赖并避免依赖地狱

  • 将依赖下载到文件夹中

  • 理解 SNAPSHOT 依赖

  • 处理依赖下载错误

  • 检测未使用/未声明的依赖

  • 手动安装仓库中不可用的依赖

  • 使用 Eclipse 进行依赖管理

  • 使用 NetBeans 进行依赖管理

  • 使用 IntelliJ IDEA 进行依赖管理

简介

Maven 的强大功能之一是管理项目所需的依赖。一个项目在没有使用其他依赖的情况下开发是很罕见的。使用依赖的典型问题与依赖的数量和选择、它们的版本以及传递依赖(一个项目依赖反过来又依赖于其他依赖)有关。

Maven 有一种管理依赖的方式,同时也为用户提供足够的灵活性来处理出现的复杂性。

选择依赖的范围

我们可能出于许多原因使用依赖。其中一些可能是为了编译和运行项目所必需的。可能还有其他仅用于运行测试的(例如,junit)。然后可能有在运行时必需的依赖,比如 logback

如何做到这一点...

使用以下步骤来选择依赖的范围:

  1. 打开我们之前创建的 Maven 项目。

  2. 观察以下部分:

    <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
    
  3. 删除前面的代码行并运行以下命令:

    mvn compile
    
    
  4. 观察到它运行时没有任何问题。

  5. 现在,运行以下命令:

    mvn test
    
    
  6. 注意以下错误:

    [INFO] Compiling 1 source file to C:\projects\apache-maven-cookbook\project-with
    -dependencies\target\test-classes
    [INFO] -------------------------------------------------------------
    [ERROR] COMPILATION ERROR:
    [INFO] -------------------------------------------------------------
    [ERROR] /C:/projects/apache-maven-cookbook/project-with-dependencies/src/test/java/com/packt/cookbook/AppTest.java:[3,23] package junit.framework does not exist
    
    

它是如何工作的...

Java 源代码 App.java 没有任何依赖。只有源类被 mvn 编译,因此命令运行时没有出现任何错误。

测试代码 AppTest.java 需要使用 junit 库进行构建。这在代码的导入语句中声明。mvn 测试尝试编译测试类,由于没有找到依赖,它失败了。

声明依赖需要指定以下信息:

      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>

前三个元素唯一地标识了依赖。

第四条信息如下:

<scope>test</scope>

默认情况下,scopecompile

有六个不同的依赖范围可供选择:

  • compile:这个依赖对于编译是必需的。这自动意味着它对于测试以及运行时(当项目运行时)也是必需的。

  • test:这个依赖仅用于测试。这意味着依赖通常在测试代码中。由于测试代码不用于运行项目,因此这些依赖在运行时不必要。

  • runtime:这些依赖在编译期间不是必需的,但运行项目时是必需的。一个例子是,如果你使用 Java 简单日志门面(slf4j)进行日志记录并希望使用 logback 绑定,那么就需要 logback 依赖。

  • provided:这告诉 Maven 依赖项对于编译和运行是必需的,但这个依赖项不需要与打包的分发包一起打包。依赖项将由用户提供。这种依赖项的一个例子是 servlet-api。通常,应用服务器有这些库。

  • system:这与提供的范围相似。在这里,我们需要明确提供 JAR 文件的路径。它不会从仓库中查找。这可能有助于指定不在仓库中的依赖项:

      <dependency>
          <groupId>com.myorg</groupId>
          <artifactId>some-jar</artifactId>
          <version>2.0</version>
          <scope>system</scope>
          <systemPath>${basedir}/lib/some.jar</systemPath>
        </dependency>
    
  • import:这仅在 dependencyManagement 部分的 pom 类型依赖项上使用。它表示指定的 pom 应该用该 pom 的 dependencyManagement 部分中的依赖项替换。这是为了集中管理大型多模块项目的依赖项。

参见

  • 本章中 手动安装仓库中不可用的依赖项 的配方

获取依赖关系报告

获取 Maven 项目的依赖关系列表对于识别和调试问题非常有用。Maven Dependency 插件在这里帮了我们大忙。

准备工作

要欣赏这一点,我们需要一个相当复杂的项目,它有几个传递依赖。您可以在 github.com/selendroid/demoproject-selendroid 上查看这样一个项目。

项目源代码以 Git 仓库的形式提供。通常通过克隆来下载 Git 仓库。为此,请在您的系统上安装 Git。有关详细说明,请参阅 Git 设置链接 (help.github.com/articles/set-up-git/)。

如何操作...

使用以下步骤,获取 Maven 项目的依赖关系列表:

  1. 克隆开源项目 demoproject-selendroid

  2. 运行以下 Maven 目标:

    mvn dependency:list
    
    
  3. 观察以下截图所示的输出:如何操作...

它是如何工作的...

Maven Dependency 插件有几个目标,用于获取有关依赖项的信息以及管理它们。

有趣的是,这个目标并不绑定到 Maven 的任何阶段或生命周期。这意味着,当运行 mvn dependency:list 命令时,Maven 只会运行 list 目标,而不会做其他任何事情。

dependency:list 参数告诉 Maven 运行 Maven Dependency 插件的 list 目标。这会分析 pom 文件并生成项目的依赖关系列表。

还有更多...

虽然依赖关系列表对于简单情况可能足够好,但更有趣和有用的是以树形格式显示的依赖关系报告。

这可以通过运行 Maven Dependency 插件的 tree 目标来完成:

mvn dependency:tree

在前面的项目上运行此命令会得到以下输出:

还有更多...

如我们所见,这是依赖关系传递性的更好表示。现在我们知道哪些其他依赖项被使用了,例如,commons-logging

进入依赖关系并避免依赖关系地狱

随着您使用越来越多的依赖关系,每个依赖关系反过来也可能包含更多的依赖关系。可能会出现项目中有多个相同依赖关系版本的情况。这通常会导致错误。

准备工作

要理解这一点,我们需要一个相当复杂的项目,它有几个传递依赖关系。您可以在github.com/selendroid/demoproject-selendroid查看这样一个项目。

在您的系统上克隆仓库。现在,我们准备了解复杂依赖关系可能变得多么复杂。

如何操作...

使用以下步骤来避免依赖关系地狱:

  1. 运行以下命令:

    mvn dependency:tree -Dverbose
    
    
  2. 注意以下截图所示的输出:如何操作...

它是如何工作的...

正如您所看到的,在确定项目要使用的依赖关系的过程中,Maven 执行依赖关系分析。这揭示了两个问题:

  • 两个或多个依赖关系需要另一个依赖关系的相同版本。Maven 只包含一次依赖关系。

  • 两个或多个依赖关系需要另一个依赖关系的不同版本。

Maven 通过支持最近定义来解决这个问题,这意味着它将使用与您的项目在依赖关系树中最接近的依赖关系的版本。

这意味着它不一定选择最新的或最旧的版本。它将按照依赖关系的顺序,找到的第一个版本。

当项目由于使用了错误的版本而无法工作时,正确的解决方法是明确在您的 pom 文件中定义所需的依赖关系版本。根据前面的策略,这将作为最近定义将优先于任何其他依赖关系中定义的任何其他版本。

更多...

Maven 提供了另一种处理上述场景的方法,即通过使用dependencyManagement元素。

这允许我们在遇到传递依赖关系或未指定版本的依赖关系时,直接指定要使用的工件版本。在前面章节的示例中,guava依赖关系直接添加到demoproject-selendroid中,即使它没有被项目直接使用。相反,demoproject-selendroid可以在其dependencyManagement部分将guava作为依赖关系包含,并直接控制何时或是否引用它时使用哪个版本的guava

没有魔法子弹可以防止依赖关系地狱。即使您手动管理通过前面机制包含在您的项目中的库的版本,这也并不意味着其他依赖于同一库不同版本的传递依赖关系会突然与管理的版本二进制兼容。

将依赖关系下载到文件夹中

一些项目可能需要将所有依赖项都可用,例如,在一个文件夹中。这可能是为了存档特定构建版本中使用的依赖项。

如何操作...

使用以下步骤在 target/dependency 文件夹中下载依赖项:

  1. 让我们打开之前菜谱中使用的演示项目。

  2. 运行以下命令:

    mvn dependency:copy-dependencies
    
    
  3. target/dependency 文件夹中查看输出:如何操作...

它是如何工作的...

Maven Dependency 插件的 copy-dependencies 目标会将项目中使用的所有依赖项(包括传递依赖项)复制到项目的 target/dependency 文件夹中。

还有更多...

此目标接受多个参数来处理各种用例,例如复制依赖项的 pom 文件、复制父 pom、保留仓库的文件夹结构等。

可以通过传递以下参数来更改文件夹位置:

mvn dependency:copy-dependencies -DoutputDirectory=dependencies

现在依赖项将被复制到 dependencies 文件夹而不是默认的 target/dependency 文件夹。

可以通过运行以下命令保留仓库的文件夹结构并将依赖项的 pom 复制过来:

mvn dependency:copy-dependencies -Dmdep.copyPom=true Dmdep.useRepositoryLayout=true

生成的文件夹结构将类似于以下截图所示的仓库布局:

还有更多...

理解 SNAPSHOT 依赖项

在 Maven 中,SNAPSHOT 版本是项目/依赖项尚未发布的版本。这通过在版本号后附加 SNAPSHOT 来表示。以下是一个示例:

<version>1.0-SNAPSHOT</version>

您会注意到我们使用 Maven 架构快速启动创建的项目有一个 SNAPSHOT 版本。

-SNAPSHOT 前指定的版本号是预期发布的项目/依赖项应具有的版本。因此,1.0-SNAPSHOT 表示 1.0 尚未发布。

由于 SNAPSHOT 版本表示正在开发中的软件,Maven 会以不同的方式处理这些依赖项。

如何操作...

很少会使用外部依赖项的 SNAPSHOT 版本。如果您在您的组织中开发一个多模块项目,那么您可能会使用项目中需要的其他模块的 SNAPSHOT 版本。

让我们尝试以下虚构的示例:

  1. 打开我们创建的一个项目。

  2. 添加以下依赖项:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.0.BUILD-SNAPSHOT</version>
    </dependency>
    
  3. 添加以下代码以指定依赖项可用的仓库:

    <repositories>
        <repository>
            <id>repository.spring.snapshot</id>
            <name>Spring Snapshot Repository</name>
            <url>http://repo.spring.io/snapshot</url>
        </repository>
    </repositories>
    
  4. 运行以下命令:

    C:\projects\apache-maven-cookbook\project-with-snapshot-dependencies>mvn verify
    
  5. 观察以下结果:

    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Project with SNAPSHOT dependencies 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    Downloading:http://repo.spring.io/snapshot/org/springframework/spring-context/4.1.2.BUILD-SNAPSHOT/maven-metadata.xml
    Downloaded:http://repo.spring.io/snapshot/org/springframework/spring-context/4.1.2.BUILD-SNAPSHOT/maven-metadata.xml (3 KB at 1.7 KB/sec)
    Downloading:http://repo.spring.io/snapshot/org/springframework/spring-context/4.1.2.BUILD-SNAPSHOT/spring-context-4.1.2.BUILD-20141107.161556-92.pom
    Downloaded:http://repo.spring.io/snapshot/org/springframework/spring-context/4.1.2.BUILD-SNAPSHOT/spring-context-4.1.2.BUILD-20141107.161556-92.pom (5 KB at 6.8 KB/sec)
    
    

它是如何工作的...

您首先会看到需要定义一个特定的仓库来下载依赖项。这些依赖项不在常规仓库中。它们位于称为 快照仓库 的单独仓库中。在先前的示例中,我们指定了包含所需依赖项的快照仓库。

你会注意到的第二件事是文件名。每个正在下载的工件都会附加20141107.161556-92。这是仓库中每个SNAPSHOT版本的唯一标识符。每次仓库中有新的SNAPSHOT版本可用时,此值都会改变。

Maven 对待SNAPSHOT版本和发布版本的方式不同。

对于发布版本,Maven 会检查该工件是否已存在于已下载的本地仓库中。如果是这样,它将不会尝试从远程仓库中获取相同的工件。

对于SNAPSHOT版本,即使工件在本地可用,它也会根据可以配置的更新策略在远程仓库中检查SNAPSHOT版本的更新。

默认情况下,更新间隔是一天一次。这意味着,如果 Maven 今天中午下载了一个SNAPSHOT依赖项,它将在明天中午检查其更新,而不会在此之前,无论你构建项目多少次。

更新间隔可以在 pom 或 settings 文件的仓库部分指定如下:

<updatePolicy>always<updatePolicy>

选项有alwaysdaily(默认)、interval:X(其中X是分钟内的一个整数)或never。让我们简要讨论这些选项:

  • always:这会在每次 Maven 运行时检查更新。

  • daily:这会每天检查一次更新。这并不一定意味着从上次检查的 24 小时后;只是在每天的开始。

  • interval:X:这会在指定的时间后检查更新。

    小贴士

    在多模块项目中,对于模块间的依赖项,将updatePolicy元素值设置为always是很好的。

还有更多...

如前所述,发布版本和快照版本有单独的仓库。默认情况下,快照在发布仓库中是禁用的,反之亦然。repository元素有单独的releasessnapshots子元素,可以在其中指定:

       <repository>
          <id>my-repo</id>
          <name>My Release Repo</name>
          <releases>
            <enabled>true</enabled>
            <updatePolicy>never</updatePolicy>
            <checksumPolicy>fail</checksumPolicy>
          </releases>
          <snapshots>
            <enabled>false</enabled>
            <updatePolicy>always</updatePolicy>
            <checksumPolicy>fail</checksumPolicy>
          </snapshots>
          <url>http://my.repo.url</url>
          <layout>default</layout>
        </repository>

通常,对于发布仓库,snapshotsenabled将为false。对于快照仓库,snapshotsenabled将为true,而releasesenabled将为false。这样,Maven 每次需要依赖项时都会查看正确的仓库,而不会不必要地查看错误的仓库。

checksumPolicy元素告诉 Maven 在下载的依赖项的校验和与实际校验和不匹配时应该做什么。fail的值将在校验和错误时停止构建。

处理依赖项下载错误

可能会有一些情况,由于网络问题或其他问题,依赖项可能无法下载。有时,Maven 报告的错误可能不会表明问题。了解如何解决这个问题是很有用的。

如何做到这一点...

在正常情况下模拟这个问题是困难的,但我们可以通过以下步骤创建一个人为的场景:

  1. 修改我们简单项目中 JUnit 的依赖版本:

    <version>3.9.1 </version>
    
  2. 运行以下命令:

    mvn verify
    
    
  3. 这将尝试下载依赖项并失败(因为版本无效):

    [INFO] Building simple-project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    Downloading:https://repo.maven.apache.org/maven2/junit/junit/3.9.1/junit-3.9.1.pom
    [WARNING] The POM for junit:junit:jar:3.9.1 is missing, no dependency information available
    Downloading:https://repo.maven.apache.org/maven2/junit/junit/3.9.1/junit-3.9.1.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 3.329 s
    [INFO] Finished at: 2014-11-08T15:59:33+05:30
    [INFO] Final Memory: 7M/154M
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal on project simple-project: Could not resolve dependencies for project com.packt.cookbook:simple-project:jar:1.0-SNAPSHOT: Could not find artifact junit:junit:jar:3.9.1 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
    
    
  4. 再次运行命令并观察结果:

    [ERROR] Failed to execute goal on project simple-project: Could not resolve dependencies for project com.packt.cookbook:simple-project:jar:1.0-SNAPSHOT: Failure to find junit:junit:jar:3.9.1 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]
    
    
  5. 删除本地仓库(.m2/repository/junit/junit/3.9.1)中的文件夹3.9.1(或以.lastUpdated结尾的文件夹中的文件)并重试。

    “无法尝试解决”错误将消失,Maven 将再次尝试下载依赖项。

它是如何工作的...

Maven 首先下载依赖项的 pom 文件。它分析 pom 文件,并递归地下载那里指定的传递依赖项。然后下载实际的依赖项文件,通常是 JAR 文件。

当 Maven 无法下载一个工件时,它会创建一个与未能下载的工件同名的文件,但后缀为.lastUpdated。在该文件中,它放入与下载相关的信息,如下例所示:

#NOTE: This is an Aether internal implementation file, its format can be changed without prior notice.
#Sat Nov 08 15:59:33 IST 2014
https\://repo.maven.apache.org/maven2/.lastUpdated=1415442573938
https\://repo.maven.apache.org/maven2/.error=

当请求 Maven 再次下载依赖项时,Maven 会参考此文件的内容来决定是否应该重新尝试。这是针对发布依赖项的情况。删除此文件将确保 Maven 在请求时重新尝试下载依赖项。

我们已经在本章的“理解 SNAPSHOT 依赖”食谱中看到了这是如何为 SNAPSHOT 依赖项工作的。

检测未使用/未声明的依赖项

随着项目变得越来越大,依赖项的数量(包括传递依赖项)增加,了解我们是否最终声明了未使用的依赖项,或者我们是否使用了未声明的依赖项(这些依赖项是通过传递依赖项引入的)是有好处的。

如何操作...

使用以下步骤来检测未使用/未声明的依赖项:

  1. 在我们之前使用的demo-selendroid项目上运行以下 Maven 命令:

    mvn dependency:analyze
    
    
  2. 注意生成的报告:

    [WARNING] Used undeclared dependencies found:
    [WARNING]    org.seleniumhq.selenium:selenium-api:jar:2.43.1:compile
    [WARNING]    org.hamcrest:hamcrest-library:jar:1.3:compile
    [WARNING]    io.selendroid:selendroid-common:jar:0.12.0:compile
    [WARNING] Unused declared dependencies found:
    [WARNING]    org.hamcrest:hamcrest-integration:jar:1.3:compile
    
    

它是如何工作的...

如前述报告所示,Maven 已经识别出项目使用的一个未声明的依赖项,例如selenium-api JAR 文件。它还发现了一个在 pom 文件中声明但未被项目使用的依赖项(hamcrest-integration)。您可以检查删除是否会引起任何副作用,如果没有,则继续操作。

明确定义项目中使用的依赖项,指定版本号而不是通过传递依赖项使用它,这是一个好习惯。这是因为我们无法控制这个传递依赖项的版本或可用性。

另一方面,为了更好地控制我们之前看到的依赖项冲突,明确定义那些不是直接由我们的项目要求但由我们的依赖项使用的依赖项的版本可能不是一个坏主意。

在仓库中不可用的依赖项的手动安装

可能存在这样的情况,需要使用一个不在任何 Maven 仓库中的库。我们已看到一种使用方法,即将其指定为具有 system 范围的依赖项,并明确指定其路径。

这种方法的缺点是,如果您需要将项目作为库分发,则此依赖项将不可用。

Maven 提供了一种机制,可以将工件安装到您的本地仓库,以便您可以像其他依赖项一样声明和使用它。

如何操作...

使用以下步骤手动安装仓库中不可用的依赖项:

  1. 将以下依赖项添加到我们之前创建的简单项目中:

    <dependency>
          <groupId>org.apache.tomcat</groupId>
          <artifactId>apache-tomcat</artifactId>
          <version>8.0.14</version>
          <type>tar.gz</type>
          </dependency>
    

    项目将因缺少依赖项而编译失败

  2. 现在运行以下 Maven 命令:

    C:\projects\apache-maven-cookbook\project-with-dependency-not-in-repo>mvn install:install-file -DgroupId=org.apache.tomcat -DartifactId=apache-tomcat -Dversion=8.0.14 -Dpackaging=tar.gz -Dfile=C:\Users\raghu\Downloads\apache-tomcat-8.0.14.tar.gz -DgeneratePom=true
    
    
  3. 注意结果:

    [INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ project-with-dependency-not-in-repo ---
    [INFO] Installing C:\Users\raghu\Downloads\apache-tomcat-8.0.14.tar.gz to C:\software\maven\org\apache\tomcat\apache-tomcat\8.0.14\apache-tomcat-8.0.14.tar.gz
    [INFO] Installing 
    C:\Users\raghu\AppData\Local\Temp\mvninstall8295760271813162395.pom to C:\software\maven\org\apache\tomcat\apache-tomcat\8.0.14\apache-tomcat-8.0.14.pom
    
    

它是如何工作的...

Maven Install 插件的 install-file 目标允许将依赖项安装到本地仓库。它接受 groupIdartifactIdversionpackaging 类型作为参数,以便它可以在仓库中适当地放置依赖项,并为它创建一个简单的 pom 文件。

在有多个开发者的项目中,这种方法并不理想,因为每个开发者都需要手动执行此步骤。一种处理方法是将此依赖项安装到组织使用的仓库管理器中。因为开发者将使用此仓库管理器作为 mirror,所以 Maven 将从 mirror 中找到依赖项并继续执行。

在这种情况下,我们可以使用 Maven deploy 插件的 deploy 目标将工件安装到远程仓库。

一些远程仓库有访问控制。Maven 允许在 server 元素中指定访问详情。最好在 settings.xml 中指定此内容,因为此文件对每个用户都是特定的。

还有更多...

使用这种方法安装依赖项的项目再次不可分发,因为使用它们的人将无法找到依赖项。

当项目预期被他人作为依赖项分发和包含时,需要遵循不同的方法——即静态 项目内仓库 解决方案。使用以下步骤遵循项目内仓库方法:

  1. 在您的 pom 文件中添加以下内容以在项目中创建一个仓库:

    <repository>
        <id>in-project-repo</id>
        <releases>
            <checksumPolicy>ignore</checksumPolicy>
        </releases>
        <url>file://${project.basedir}/lib</url>
    </repository>
    
  2. 使用以下命令将依赖项安装到该仓库:

    mvn install:install-file -DgroupId=org.apache.tomcat -DartifactId=apache-tomcat -Dversion=8.0.14 -Dpackaging=tar.gz -Dfile=C:\Users\raghu\Downloads\apache-tomcat-8.0.14.tar.gz -DgeneratePom=true -DlocalRepositoryPath=lib
    
    

我们取得了什么成果?现在,依赖项已与源代码一起打包到我们项目的 lib 文件夹中,并可供分发。这对用户来说是透明的,因为他们不需要做任何特殊操作来访问它。

使用 Eclipse 进行依赖项管理

我们已经看到 Eclipse IDE 提供了对 Maven 项目的支持,并允许我们从 IDE 中运行 Maven 命令。现在让我们看看如何使用 Eclipse 管理依赖项。

如何操作...

在 Eclipse IDE 中使用以下步骤来管理依赖项:

  1. 在 Eclipse 中打开 demoproject-selendroid 文件。

  2. 打开 pom.xml 文件。

  3. 点击以下截图所示的 依赖项 选项卡:如何操作...

  4. 可以通过点击 添加… 按钮(参见前面的截图中的 添加… 按钮)来添加新的依赖项:如何操作...

    如前一个截图所示,您可以在 组 ID:组件 ID:版本: 文本框中指定值,以及 作用域 下拉列表中的值。或者,您可以在 输入组 ID、组件 ID 或 sha1 前缀或模式 (*): 文本框中搜索一个组件,Eclipse 将根据您在 搜索结果 列表中的选择填充相关列。

  5. 您还可以通过点击 依赖关系层次结构 选项卡来查看依赖关系树:如何操作...

工作原理...

由于 Eclipse 内置了对 Maven 的支持,它可以通过解析 pom 文件来可视化依赖项。它还内部调用各种 Maven 命令(如 dependency:tree)来构建层次结构并显示相同的内容。

更多内容...

我们看到用户可以搜索并添加依赖项。为了使此功能正常工作,请导航到 Windows | 首选项 | Maven 并勾选 启动时下载仓库索引更新 选项以下载索引,如图所示:

更多内容...

您可能需要重新启动 Eclipse 以使此更改生效。此外,您还可以启用 Maven 仓库 视图(参见前面的截图),查看仓库,并根据需要更新索引。

使用 NetBeans 进行依赖项管理

与 Eclipse 类似,NetBeans 也允许通过 IDE 管理和查看依赖项。与 Eclipse 不同,NetBeans 显示了依赖项的图形视图以及附加信息,这使得开发者更容易排查问题。

如何操作...

在 NetBeans IDE 中使用以下步骤来管理依赖项:

  1. 在 NetBeans 中打开 demoproject-selendroid 文件。

  2. 打开 pom.xml 文件。

  3. 点击 图形 选项卡:如何操作...

  4. 将鼠标悬停在红色依赖项之一(commons-codec)上:如何操作...

  5. 将鼠标悬停在橙色依赖项之一(httpclient)上:如何操作...

工作原理...

NetBeans 创建了一个包含所有项目依赖关系的图表,并显示相同的内容。它用红色突出显示有冲突的依赖项,用橙色突出显示有警告的依赖项。在悬停时,NetBeans 显示问题的详细信息。

这允许用户采取适当的行动。

使用 IntelliJ IDEA 进行依赖项管理

与 Eclipse 和 NetBeans 不同,只有在 IntelliJ IDEA Ultimate 版本中才能以图形的形式查看依赖项,这是一个商业版本。社区版不支持此选项。

如何操作...

在 IntelliJ IDEA Ultimate 版本中使用以下步骤来管理依赖项:

  1. 在 IntelliJ IDEA Ultimate 版本中打开 demoproject-selendroid 文件。

  2. 右键单击 pom.xml 文件。如何操作...

  3. 点击 显示依赖... 选项(参见前面的截图中的此选项)并观察以下截图:如何操作...

它是如何工作的...

IntelliJ IDEA 对 Maven 项目提供了一级支持。它读取项目的 pom.xml 文件,解析它,并识别所有依赖项,包括传递依赖项。然后以图形方式显示这些依赖项,使用户能够可视化项目。

第六章。代码质量插件

在本章中,我们将回顾一些可用于 Java 语言的工具,以及如何在 Maven 上下文中使用它们。我们将涵盖以下食谱:

  • 使用 Maven JaCoCo 插件分析代码覆盖率

  • 使用 Maven Cobertura 插件分析代码覆盖率

  • 使用 Maven PMD 插件分析代码

  • 使用 Maven Checkstyle 插件分析代码

  • 使用 Maven FindBugs 插件分析代码

  • 使用 Maven JXR 插件生成源引用

  • 使用 Maven SonarQube 插件分析代码

简介

编写代码和编写优秀的代码是两回事。通过拥有编码指南/标准,代码质量的主体性得到了极大的降低。开发者是否遵循编码标准可以通过对代码进行代码审查来验证。另一方面,有一些工具可以自动执行这些审查,与定义的标准进行对比。

除了代码质量,编程最佳实践还建议为代码编写自动单元测试。这些单元测试实现的行和分支覆盖率也可以通过工具进行定量测量。

使用 Maven JaCoCo 插件分析代码覆盖率

JaCoCo 是一个免费的 Java 代码覆盖率工具。这实际上是 Emma 的继任者,它是由 EclEmma 团队作为 Eclipse 项目开发的。

JaCoCo 提供行和分支覆盖率。

准备工作

Maven 已在您的系统上设置并验证其工作。为此,请参考第一章的前三个食谱,入门

如何操作...

使用以下步骤使用 Maven JaCoCo 插件分析代码覆盖率:

  1. 打开具有单元测试的项目(例如,project-with-tests)的 pom 文件。

  2. 添加以下代码:

    <plugin>
      <groupId>org.jacoco</groupId>
      <artifactId>jacoco-maven-plugin</artifactId>
      <version>0.7.2.201409121644</version>
      <executions>
         <execution>
           <id>default-prepare-agent</id>
           <goals>
             <goal>prepare-agent</goal>
           </goals>
         </execution>
         <execution>
           <id>default-report</id>
           <phase>prepare-package</phase>
           <goals>
             <goal>report</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
    
  3. 从命令提示符运行以下命令:

    mvn package
    
    
  4. 注意前面命令的输出:

    [INFO] --- jacoco-maven-plugin:0.7.2.201409121644:prepare-agent (default-prepare-agent) @ project-with-tests ---
    [INFO] argLine set to -javaagent:C:\\software\\maven\\org\\jacoco\\org.jacoco.agent\\0.7.2.201409121644\\org.jacoco.agent-0.7.2.201409121644-runtime.jar=destfile=C:\\projects\\apache-maven-cookbook\\project-with-tests\\target\\jacoco.exec
    [INFO] --- jacoco-maven-plugin:0.7.2.201409121644:report (default-report) @ project-with-tests ---
    [INFO] Analyzed bundle 'Project with Tests with 1 classes
    
    
  5. 打开在 target/site/jacoco 文件夹中生成的 index.html 文件:如何操作...

它是如何工作的...

在 pom 文件中,我们指示 Maven 运行 Maven JaCoCo 插件的以下两个目标:

  • prepare-agent:默认情况下,它与 Maven 默认生命周期的 initialize 阶段绑定。目标运行并准备执行分析的分析代理。

  • report:当运行测试时,此代理收集测试覆盖率信息,并在 prepare-package 阶段(我们已明确指定)中创建报告。

报告提供了关于测试覆盖率的详细信息。绿色表示被测试覆盖的行,红色表示未被测试覆盖的行。在上面的示例中,12/19 指令未被测试覆盖。

还有更多...

您可以对项目进行代码覆盖率分析并生成相同的报告,而无需对 pom 文件进行任何更改。为此,请运行以下命令:

mvn jacoco:prepare-agent test jacoco:report

现在,您可能会遇到以下错误:

[ERROR] No plugin found for prefix 'jacoco' in the current project and in the plugin groups [org.apache.maven.plugins] available from the repositories [local (C:\software\maven), central (https://repo.maven.apache.org/maven2)] -> [Help 1]

为了解决这个问题,明确指定插件的 groupIdartifactId 参数。在 第八章 的 配置 Maven 以搜索插件 菜谱中,我们将看到解决此问题的另一种方法。

在以下代码中,我们将明确调用之前看到执行的相关目标。所以首先运行 prepare-agent,然后是 test,最后是 report 目标:

mvn org.jacoco:jacoco-maven-plugin:prepare-agent test org.jacoco:jacoco-maven-plugin:report

如果代码覆盖率低于阈值值时失败构建怎么办?为此,执行以下步骤:

  1. 将以下执行块添加到之前指定的 build 部分的插件配置中:

    <execution>
        <id>default-check</id>
        <phase>prepare-package</phase>
        <goals>
            <goal>check</goal>
        </goals>
        <configuration>
            <rules>
                <rule>
                    <element>BUNDLE</element>
                    <limits>
                        <limit>
                            <counter>COMPLEXITY</counter>
                            <value>COVEREDRATIO</value>
                            <minimum>0.60</minimum>
                        </limit>
                    </limits>
                </rule>
            </rules>
        </configuration>
    </execution>
    
  2. 运行以下命令:

    mvn package
    
    
  3. 观察以下截图所示的结果:还有更多...

使用 Maven Cobertura 插件分析代码覆盖率

Cobertura 是另一个流行的 Java 工具,它计算测试访问的代码百分比。它基于 jcoverage。使用 Cobertura 有许多方式,包括独立使用、通过 Ant 脚本和 Maven。让我们使用 Maven Cobertura 插件。

如何操作...

使用以下步骤使用 Maven Cobertura 插件分析代码覆盖率:

  1. 打开一个具有单元测试的 Maven 项目(例如,project-with-tests)。

  2. 运行以下命令:

    mvn cobertura:cobertura
    
    
  3. 观察以下输出:

    [INFO] <<< cobertura-maven-plugin:2.6:cobertura (default-cli) < [cobertura]test@ project-with-tests <<<
    [INFO]
    [INFO] --- cobertura-maven-plugin:2.6:cobertura (default-cli) @ project-with-tests ---
    [INFO] Cobertura 2.0.3 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
    Report time: 165ms
    [ERROR] Nov 15, 2014 5:06:25 PM
    net.sourceforge.cobertura.coveragedata.CoverageDataFileHandler loadCoverageData
    INFO: Cobertura: Loaded information on 1 classes.
    
    
  4. 查看生成的报告:如何操作...

工作原理...

JaCoCo 在测试运行时在线对代码进行仪器化,因此需要运行代理。另一方面,Cobertura 在离线编译期间对字节码进行仪器化。Cobertura Maven 插件的 cobertura 目标对项目进行仪器化,运行测试并生成报告。

如果需要,有单独的目标用于 instrumentcheck 结果。

还有更多...

如果我们想在代码覆盖率低于阈值时失败构建,我们可以设置 Cobertura 来实现这一点:

  1. 将以下内容添加到 pom 文件中:

         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>cobertura-maven-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <check>
                <branchRate>85</branchRate>
                <lineRate>85</lineRate>
                <haltOnFailure>true</haltOnFailure>
              </check>
            </configuration>
            <executions>
              <execution>
                <goals>
                  <goal>check</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
    
  2. 运行以下命令:

    mvn cobertura:check
    
    
  3. 观察以下截图所示的结果:还有更多...

构建失败,因为在 pom 文件中,我们指定了如果覆盖率低于 85%,则应停止构建。

使用 Maven PMD 插件分析代码

PMD 是一个源代码分析器。它查找常见的编程缺陷,如未使用的变量、空的 catch 块和不必要的对象创建。它还包括 复制/粘贴检测器CPD),用于查找重复的代码。

如何操作...

使用以下步骤在 Maven 项目上运行 PMD:

  1. 打开你想要进行 PMD 分析的 Maven 项目(例如,project-with-violations)。

  2. 运行以下命令:

    mvn pmd:pmd pmd:cpd
    
    
  3. 观察输出:

    [INFO] --- maven-pmd-plugin:3.2:pmd (default-cli) @ project-with-violations ---
    [WARNING] Unable to locate Source XRef to link to – DISABLED
    [INFO] --- maven-pmd-plugin:3.2:cpd (default-cli) @ project-with-violations ---
    [WARNING] Unable to locate Source XRef to link to - DISABLED
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    
    
  4. 检查 target 文件夹的内容:如何操作...

  5. 打开 pmd.xml 报告:如何操作...

  6. site 文件夹中打开 cpd.html 文件:如何操作...

它是如何工作的...

Maven PMD 插件的 pmdcpd 目标没有绑定到任何阶段。它们也分析 Java 源代码,因此不需要运行任何其他 Maven 阶段或目标。

当运行 pmd 目标时,它使用默认规则集和插件中设置的配置生成 PMD 站点报告。它还生成一个 XML 格式的 pmd 输出文件。

您也可以定义自己的自定义规则集。为此,在 pom 文件的 configuration 部分添加以下代码:

<reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
        <version>3.4</version>
        <configuration>
          <rulesets>
            <!-- Two rule sets that come bundled with PMD -->
            <ruleset>/rulesets/java/braces.xml</ruleset>
            <ruleset>/rulesets/java/naming.xml</ruleset>
            <!-- Custom local file system rule set -->
            <ruleset>d:\rulesets\strings.xml</ruleset>
            <!-- Custom remote rule set accessed via a URL -->
            <ruleset>http://localhost/design.xml</ruleset>
          </rulesets>
        </configuration>
      </plugin>
    </plugins>
  </reporting>

同样,当运行 cpd 目标时,它会为重复代码生成类似的报告。默认情况下,它认为报告代码重复的最小令牌计数是 100 个令牌(这通常是 10 行代码)。

还有更多...

可以通过以下方式使用插件的 check 目标使构建失败:

  1. 将以下代码添加到 project-with-violations 的 pom 文件中:

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-pmd-plugin</artifactId>
          <version>3.4</version>
          <executions>
            <execution>
              <goals>
                <goal>check</goal>
                <goal>cpd-check</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    
  2. 运行以下命令:

    mvn verify
    
    
  3. 观察以下截图中的输出结果:还有更多...

使用 Maven Checkstyle 插件分析代码

Checkstyle 是一个帮助程序员遵循编码标准的工具。它自动化了检查定义的编码标准是否被遵循的过程。它可以通过适当的配置支持任何编码标准。像其他工具一样,它既可以独立运行,也可以与 Maven 集成。

如何操作...

使用以下步骤使用 Maven Checkstyle 插件分析代码:

  1. 打开您要进行 Checkstyle 分析的 Maven 项目(例如,project-with-violations)。

  2. 运行以下命令:

    mvn checkstyle:checkstyle
    
    
  3. 观察以下截图中的输出结果:

    [INFO]
    [INFO] --- maven-checkstyle-plugin:2.13:checkstyle (default-cli) @ project-with-violations ---
    [INFO]
    [INFO] There are 29 checkstyle errors.
    [WARNING] Unable to locate Source XRef to link to - DISABLED
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    
    
  4. target 文件夹中打开 checkstyle-result.xml 报告:如何操作...

它是如何工作的...

与 Maven 的 pmdcheckstyle 目标不同,Checkstyle 插件没有绑定到任何阶段。

当运行 checkstyle 目标时,它使用默认规则集和插件中设置的配置生成 Checkstyle 站点报告。它还生成一个 XML 格式的 Checkstyle 输出文件。

Maven Checkstyle 插件支持多个配置选项来定制规则、排除要检查的文件等。让我们简要讨论一些示例,展示 Maven Checkstyle 插件在高级用例中的使用:

  1. Checkstyle 规则可以内联在插件的 configuration 部分中指定:

    <configuration>
      <checkstyleRules>
        <module name="Checker">
          <module name="TreeWalker">
            <module name="FinalLocalVariable">
              <property name="tokens" value="VARIABLE_DEF,PARAMETER_DEF"/>
            </module>
          </module>
        </module>
      </checkstyleRules>
    </configuration>
    
  2. 它们也可以在外部文件中指定,并使用 configLocation 元素进行引用:

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>2.14</version>
      <configuration>
        <configLocation>checkstyle.xml</configLocation>
      </configuration>
    </plugin>
    
  3. 可以创建一个 Suppressions 过滤器,告诉 Checkstyle 不要在特定文件和文件的特定部分报告违规:

    <suppressions>
      <suppress checks="JavadocStyleCheck"
                 files="GeneratedObject.java"
                 lines="50-9999"/>
      <suppress checks="MagicNumberCheck"
                 files="LegacyDatasetConvertor.java"
                 lines="221,250-295"/>
    </suppressions>
    

还有更多...

与 PMD 的情况一样,我们可以配置 Maven Checkstyle 插件,使其在出现错误时失败构建:

  1. 将以下代码添加到 project-with-violations 的 pom 文件中:

    <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <version>2.14</version>
            <executions>
              <execution>
                <id>verify-style</id>
                <phase>process-sources</phase>
                <goals>
                  <goal>check</goal>
                </goals>
              </execution>
            </executions>
          </plugin>      
        </plugins>
      </build>
    
  2. 运行以下 Maven 命令:

    mvn verify
    
    
  3. 观察以下截图所示的输出:还有更多...

使用 Maven FindBugs 插件分析代码

FindBugs 是另一个使用静态分析来检查 Java 代码中 Java 字节码中错误的工具。它基于错误模式的概念。错误模式通常是一个错误代码片段。

如何操作...

让我们看看如何使用 Maven FindBugs 插件来分析和识别代码中的缺陷:

  1. 打开你想要进行 FindBugs 分析的 Maven 项目。

  2. 运行以下命令:

    mvn clean compile findbugs:findbugs
    
    
  3. 观察输出:

    [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ project-with-violations ---
    [INFO] Changes detected - recompiling the module!
    [INFO] Compiling 1 source file to C:\projects\apache-maven cookbook\project-with-violations\target\classes
    [INFO]
    [INFO] --- findbugs-maven-plugin:3.0.0:findbugs (default-cli) @ project-with-violations ---
    [INFO] Fork Value is true
    [java] Warnings generated: 3
    [INFO] Done FindBugs Analysis....
    
    
  4. target文件夹中打开生成的 XML 文件findbugsXml.xml如何操作...

如何工作...

当运行 FindBugs 插件的findbugs目标时,它分析字节码并将错误报告到 XML 格式的输出文件中。与 Checkstyle 和 PMD 插件不同,除非配置不同,否则它不会生成默认的站点报告。

小贴士

由于 FindBugs 在字节码上工作,因此在运行 FindBugs 分析之前,项目需要先编译。否则,你将找不到任何 FindBugs 缺陷!

FindBugs 还提供了几个选项,允许你指定要包含/排除分析的类,指定要运行的规则,并在构建过程中出现错误时失败。让我们简要讨论一些描述 FindBugs 插件基本使用的示例:

  • 过滤要报告的 bug:此插件允许我们指定可以包含或排除在报告中的类和方法:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>findbugs-maven-plugin</artifactId>
            <version>3.0.1-SNAPSHOT</version>
            <configuration>
              <excludeFilterFile>findbugs exclude.xml</excludeFilterFile>
              <includeFilterFile>findbugs-include.xml</includeFilterFile>
            </configuration>
          </plugin>
    
  • 要运行的错误检测器:我们还可以指定要运行哪些检测器。这可以通过以下方式完成:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>findbugs-maven-plugin</artifactId>
            <version>3.0.1-SNAPSHOT</version>
            <configuration>
    <visitors>FindDeadLocalStores,UnreadFields</visitors>
            </configuration>
          </plugin>
    

还有更多...

你还可以启动 FindBugs GUI 以图形格式查看报告:

  1. 要这样做,请运行以下 Maven 命令:

    mvn compile findbugs:findbugs findbugs:gui
    
    
  2. 观察 FindBugs 屏幕:还有更多...

使用 Maven JXR 插件生成源引用

在运行 PMD 或 Checkstyle 插件时,你可能已经观察到以下警告:

[INFO] --- maven-pmd-plugin:3.2:pmd (default-cli) @ project-with-violations ---
[WARNING] Unable to locate Source XRef to link to – DISABLED
[INFO] --- maven-checkstyle-plugin:2.13:checkstyle (default-cli) @ project-with-violations ---
[INFO]
[INFO] There are 36 checkstyle errors.
[WARNING] Unable to locate Source XRef to link to – DISABLED

插件试图将违规行为链接到源交叉引用的特定行。由于它们无法找到此交叉引用,因此显示警告。

要生成此交叉引用,我们需要使用 Maven JXR 插件。

如何操作...

使用以下步骤使用 Maven JXR 插件生成源引用:

  1. 打开你想要运行交叉引用的项目。

  2. 运行以下 Maven 命令:

    mvn jxr:jxr
    
    
  3. 观察输出:

    [INFO]
    [INFO] --- maven-jxr-plugin:2.5:jxr (default-cli) @ project-with-violations ---
    [INFO] ------------------------------------------------------------------------
    
    
  4. 浏览target/site文件夹。如何操作...

  5. 在浏览器中打开xref文件夹的内容:如何操作...

如何工作...

当运行 Maven JXR 插件的jxr目标时,它生成项目的所有源文件的交叉引用。格式类似于 Javadoc,但点击类时,你可以看到带有行号的源代码:

如何工作...

还有更多...

一旦建立交叉引用,代码质量工具,如 PMD 和 Checkstyle,将自动使用以下步骤链接到此引用:

  1. 运行以下 Maven 命令:

    mvn jxr:jxr checkstyle:checkstyle
    
    
  2. 在浏览器中打开 Checkstyle 报告:还有更多...

您现在可以看到针对每个违规的行号,以及到交叉引用源代码行号的链接。

使用 Maven SonarQube 插件分析代码

我们在前几节中看到的每个代码分析工具都识别代码中的特定问题。虽然 Checkstyle 寻找编码指南中的违规,PMD 识别常见的编码错误,而 FindBugs 检测错误模式。

您可以将项目配置为运行所有这三个工具。此外,您还可以运行插件以识别覆盖率。您还可以通过执行项目的 SonarQube 分析来完成所有这些以及其他操作。

SonarQube 是一个用于管理代码质量的平台。它是一个基于 Web 的应用程序,其中可以配置规则、警报、阈值和其他指标。它提供了分析代码的多种方式。分析的结果可以在 Web 应用程序中查看。SonarQube 还提供了一些付费插件,例如SQALE,以及针对特定语言,如 Cobol 和 C++。

准备中...

让我们简要讨论使用 Maven SonarQube 插件的一些基本要求:

  1. 访问 SonarQube 的下载页面www.sonarqube.org/downloads/

  2. 下载最新版本。

  3. 将 ZIP 文件解压缩到您选择的文件夹中。

  4. 根据平台,按照说明启动服务器。

  5. 通过访问网页http://localhost:9000/(假设是默认安装)来确认服务器正在运行。

如何操作...

使用以下步骤使用 Maven SonarQube 插件分析代码:

  1. 打开您想要进行 SonarQube 分析的项目。

  2. 运行以下 Maven 命令:

    mvn sonar:sonar
    
    
  3. 观察以下屏幕截图所示的输出:如何操作...

  4. 访问 Sonar 网页http://localhost:9000如何操作...

  5. 点击项目链接:如何操作...

它是如何工作的...

Maven SonarQube 插件的sonar目标启动了一系列步骤,以对项目进行各种分析。根据配置,Sonar 插件执行 Checkstyle 分析、FindBugs 分析和 PMD 分析,并检测代码覆盖率、代码重复、设计问题和代码复杂性。

它将输出发送到数据库,并生成用户可以通过网页查看的报告。

如您从仪表板中看到的那样,它已生成单元测试报告以及覆盖率信息。点击链接将用户带到覆盖率详情。

它是如何工作的...

类似地,点击问题可以查看各种违规的详细信息:

它是如何工作的...

这些问题中的每一个都可以深入到行级细节,Sonar 提供了详细信息,包括修复建议。

还有更多...

SonarQube 提供了多个配置选项来指定要包含/排除的规则、要包含/排除的源文件等。配置可以通过网页界面进行,在某些情况下,也可以通过属性进行,无论是在 Maven 的设置文件中还是在命令行中。

此外,SonarQube 为 Eclipse 和 IntelliJ 提供了插件。一旦安装并配置,这些插件就会在 IDE 中直接报告特定行的违规情况。由于这并非特定于 Maven,其详细信息超出了本节范围。

第七章。报告和文档

在本章中,我们将了解如何使用 Maven Site 插件以及配置网站上的各种报告。我们将涵盖以下配方:

  • 使用 Maven Site 插件进行文档编写

  • 为网站生成 Javadoc

  • 为网站生成源交叉引用

  • 为网站生成单元测试报告

  • 为网站生成代码覆盖率报告

  • 为网站生成代码质量报告

  • 生成选择性报告

  • 发布网站

简介

Maven 最强大的功能之一是能够为项目创建文档。拥有一个可以轻松发布到网站而无需额外努力的自我文档化的项目非常有用。Maven 提供了生成此类文档的能力,称为网站报告,并将其发布到网站。

许多 Maven 插件使用 Site 功能来生成项目文档。实际上,Maven 本身也使用 Site 插件来生成其网站。

使用 Maven Site 插件进行文档编写

除了 cleandefault 生命周期,Maven 还包含一个 site 生命周期。像 clean 一样,site 也是通过 Maven 插件实现的,在这种情况下,是 Maven Site 插件。

准备工作

Maven 已在您的系统上设置并验证其工作。要执行此操作,请参阅第一章的前三个配方,入门

如何操作...

使用以下步骤使用 Maven Site 插件生成文档:

  1. 打开我们需要生成网站报告的 Maven 项目之一(例如,project-with-documentation)。

  2. 运行以下命令:

    mvn site
    
    
  3. 观察以下截图所示的输出:如何操作...

  4. 打开在 target/site 文件夹中生成的 index.html 文件:如何操作...

工作原理...

Site 是 Maven 生命周期之一。当运行 mvn site 命令时,它调用 site 生命周期的 site 阶段。Maven Site 插件的 site 目标绑定到这个阶段并被调用。

site 目标执行一系列步骤以生成报告。它使用 pom 文件中与此相关的各种元素。让我们看看默认报告中的一些项目:

工作原理...

此外,site 命令根据 pom 文件中 reporting 部分的内 容生成报告:

<reporting>
  <plugins>
    <plugin>
      <artifactId>maven-project-info-reports-plugin</artifactId>
      <version>2.0.1</version>
      <reportSets>
        <reportSet></reportSet>
      </reportSets>
    </plugin>
  </plugins>
</reporting>

许多 Maven 插件可以生成在 reporting 元素下定义和配置的报告。在以下部分中,我们将看到许多报告。

还有更多...

我们只看到了默认的 site 命令提供的功能。Maven Site 插件提供了各种配置选项,以进行更多自定义。以下是一些示例:

  • 创建不同的文档格式:网站的默认格式是 APT(几乎纯文本),一种类似维基的格式

  • 覆盖默认导航树:如果您想在网站上插入额外内容,则需要此操作

  • 创建皮肤:如果您想以不同的方式设计站点报告,则需要此操作

让我们看看如何进行一些这些操作:

  1. 将包含以下内容的site.xml文件添加到project-with-documentation项目文件夹的src\site文件夹中:

    <project   xsi:schemaLocation="http://maven.apache.org/DECORATION/1.6.0 http://maven.apache.org/xsd/decoration-1.6.0.xsd" name="Project with Documentation">
        <bannerLeft>
            <name>Left Banner</name>
            <src>images/packt.png</src>
            <href>http://www.packtpub.com</href>
        </bannerLeft>
        <body>
            <menu name="Project with Documentation">
                <item name="Overview" href="index.html"/>
            </menu>
            <menu ref="reports"/>
        </body>
    </project>
    
  2. 将名为packt.png的图片添加到src\site\resources\images文件夹中。

  3. 现在,将包含以下内容的index.apt文件添加到src\site\apt文件夹中:

    Welcome to Project with Documentation. This is a maven project created as part of apache maven cookbook by Packt Publishing.
    
    What is Project with Documentation?
    
    This maven project contains examples of how to use the site feature of maven.
    
  4. 运行以下命令:

    mvn clean site
    
    
  5. 查看生成的站点报告:还有更多...

您可以看到一个带有标志和我们所指定的内容的自定义站点页面。

为站点生成 Javadocs

使用 Javadocs 创建 Java 项目的文档。Maven 不仅提供生成 Javadocs 的支持,还提供将其作为站点一部分发布。配置在reporting元素内的插件将为站点生成内容。当它们配置在build元素内时,它们可以生成与站点无关的报告。

如何操作...

使用以下步骤生成站点的 Javadocs:

  1. 打开 Maven 项目project-with-documentation

  2. pom.xml文件中添加以下部分:

    <reporting>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-javadoc-plugin</artifactId>
          <version>2.10.1</version>
        </plugin>
      </plugins>
    </reporting>
    
  3. 运行以下命令:

    mvn site
    
    
  4. 查看生成的报告:如何操作...

  5. 点击JavaDocs链接:如何操作...

它是如何工作的...

我们将 Javadoc 插件添加到pomreporting部分。当 Site 插件运行时,它会检查此部分并运行那里配置的报告。在这种情况下,它找到了javadoc并运行了相关的插件来为项目生成 Javadoc 报告。

Maven 将来自站点页面的报告链接到项目报告部分。

还有更多...

如果我们不想对测试类进行文档化,而只想对源代码进行文档化怎么办?我们可以通过以下步骤配置插件来完成此操作:

  1. 将以下代码添加到设置report元素值为javadocreporting部分:

            <reportSets>
              <reportSet>
                <reports>
                  <report>javadoc</report>
                </reports>
               </reportSet>
            </reportSets>
    
  2. 运行以下命令:

    mvn site
    
    
  3. 打开生成的 Site 网页。网页上仅存在JavaDocs链接。Test JavaDocs链接不再存在。

为站点生成源交叉引用

在上一章中,我们看到了 Maven JXR 插件如何生成源交叉引用。在发布项目时,除了 Javadocs 之外,提供一种引用源的方法是有用的。让我们看看如何使这部分成为站点报告的一部分。

如何操作...

使用以下步骤为站点生成源交叉引用:

  1. 打开带有文档的 Maven 项目project with documentation

  2. 将以下代码添加到pom.xml文件的reporting部分:

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jxr-plugin</artifactId>
      <version>2.5</version>
    </plugin>
    
  3. 运行以下命令:

    mvn site
    
    
  4. 打开生成的站点报告:如何操作...

它是如何工作的...

将 Maven JXR 插件添加到pom.xml文件的reporting部分会自动创建项目源交叉引用。默认情况下,会生成源和测试交叉引用。与 Javadoc 一样,如果不想为测试类生成交叉引用,可以配置reportSet元素。

为网站生成单元测试报告

当我们为项目编写单元测试时,在网站文档中查看测试报告会很好。让我们看看如何做到这一点。

如何操作...

使用以下步骤为网站生成单元测试报告:

  1. 打开您想要生成网站文档的 Maven 项目(例如,project-with-documentation)。

  2. pom.xml文件的 reporting 部分添加以下代码:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
        <version>2.18</version>
    </plugin>
    
  3. 运行以下命令:

    mvn site
    
    
  4. 观察生成的网站报告:如何操作...

它是如何工作的...

如果您还记得,我们使用 Maven Surefire 插件来运行测试。Surefire 提供了一个 Surefire 报告插件。当此插件被添加到pom.xml文件的reporting部分时,它会将测试报告包含在网站文档中。

报告是相同的,无论使用 JUnit 还是 TestNG 进行单元测试。

提示

除了网站报告的格式外,TestNG 还会以不同的格式生成额外的报告。这些报告位于target文件夹中,但不属于网站文档。

为网站生成代码覆盖率报告

让我们现在将项目单元测试的代码覆盖率包含到网站文档中。

如何操作...

使用以下步骤为网站生成代码覆盖率报告:

  1. 打开您想要进行此操作的 Maven 项目(例如,project-with-documentation)。

  2. pom.xml文件的<build>部分添加以下代码:

        <plugin>
          <groupId>org.jacoco</groupId>
          <artifactId>jacoco-maven-plugin</artifactId>
          <version>0.7.2.201409121644</version>
          <executions>
              <execution>
              <id>default-prepare-agent</id>
              <goals>
                  <goal>prepare-agent</goal>
              </goals>
              </execution>
          </executions>
        </plugin>
    
  3. pom.xml文件的reporting部分添加以下代码:

    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.2.201409121644</version>
    </plugin>
    
  4. 运行以下 Maven 命令:

    mvn test site
    
    
  5. 观察以下截图所示的网站报告:如何操作...

它是如何工作的...

由于以下问题,JaCoCo 单元测试覆盖率报告出现在网站文档中:

  • 当 JaCoCo 插件的prepare-agent目标被添加到build部分时,Maven 会运行 JaCoCo 代理

  • 当运行test目标时,Maven 会运行测试,代理会分析测试覆盖率

  • 当 JaCoCo 插件被添加到pom.xml文件的reporting部分时,覆盖率报告会被生成并链接到网站文档

  • 如您所见,相同的插件被添加到buildreporting部分,但执行不同的操作

还有更多...

如果您想用 Cobertura 代替 JaCoCo 来生成测试覆盖率,您可以这样做:

  1. buildreporting部分删除与 JaCoCo 相关的行。

  2. 将以下代码添加到pom.xml文件的 reporting 部分:

          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>cobertura-maven-plugin</artifactId>
            <version>2.6</version>
          </plugin>
    
  3. 运行以下 Maven 命令:

    mvn site
    
    
  4. 打开网站文档:还有更多...

您将注意到两件事:

  • 我们不需要在build部分中指定任何内容

  • 我们不需要显式运行test目标;Maven Cobertura 插件已经完成了这项工作。

为站点生成代码质量报告

我们已经看到如何使用各种代码质量工具进行静态代码分析。现在让我们看看我们如何使用这些工具的报告来更新我们的站点文档。

如何操作...

使用以下步骤为站点生成代码质量报告:

  1. 打开我们想要生成站点报告的项目。

  2. 将以下代码添加到pom.xml文件的reporting部分:

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-pmd-plugin</artifactId>
            <version>3.3</version>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <version>2.13</version>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>findbugs-maven-plugin</artifactId>
            <version>3.0.0</version>
          </plugin>>
    
  3. 运行以下 Maven 命令:

    mvn test site
    
    
  4. 打开生成的站点报告:如何操作...

工作原理...

对于在pom.xml文件的reporting部分中指定的每个代码质量工具,site目标会运行指定的工具,生成报告,并将其链接到站点文档。

点击每个链接会将用户带到特定的报告。

还有更多...

如果您选择使用 SonarQube 进行分析,并希望将 Sonar 报告链接到站点文档,则可以执行以下操作:

  1. pom.xml文件的报告部分添加以下代码:

    <plugin>
      <groupId>org.codehaus.sonar-plugins</groupId>
      <artifactId>maven-report</artifactId>
      <version>0.1</version>
    </plugin>
    
  2. 通过运行以下 Maven 命令生成站点:

    mvn test site
    
    
  3. 打开站点报告:还有更多...

项目报告中新增了一个Sonar链接,它自动重定向到默认的 Sonar 安装。如果链接的 URL 不同,则可以自定义此链接。

生成选择性报告

我们已经看到默认情况下,site命令会生成一些项目信息。其中一些,例如邮件列表,可能不存在或不适用于项目。让我们看看我们如何避免生成这些信息。Maven 项目信息报告插件是提供 pom 中标准报告的插件。它可以配置为排除特定的报告。

如何操作...

使用以下步骤生成选择性站点报告:

  1. 打开您想要生成站点报告的项目。

  2. 将以下代码添加到pom.xml文件的reporting部分:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <version>2.7</version>
        <reportSets>
          <reportSet>
            <reports>
              <report>dependencies</report>
              <report>project-team</report>
              <report>license</report>
              <report>scm</report>
            </reports>
          </reportSet>
        </reportSets>
      </plugin>
    
  3. 运行以下 Maven site命令:

    mvn test site
    
    
  4. 打开生成的报告:如何操作...

工作原理...

我们明确指定了想要在项目信息中看到的报告。因此,只有这些报告被生成并显示。

这允许我们避免生成和显示不适用于项目的报告。

部署站点

一旦生成站点报告,就需要发布。虽然这可以手动完成,但 Maven 也提供了相应的功能。让我们看看如何操作。

准备工作

要发布站点,您需要有权访问部署站点的 Web 服务器。

如何操作...

要部署站点,请按照以下步骤操作:

  1. 将以下代码添加到您的pom.xml文件中。这也可以添加到settings.xml中:

      <distributionManagement>
        <site>
          <id>myorg</id>
          <url>scp://www.myorg.com/project/</url>
        </site>
      </distributionManagement>
    
  2. 对于相应的 ID,在你的 settings.xml 文件中添加相关的用户名和密码:

    <servers>
        <server>
          <id>myorg</id>
          <username>username</username>
          <password>password</password>
          <filePermissions>664</filePermissions>
          <directoryPermissions>775</directoryPermissions>
        </server>
      </servers>
    
  3. 运行以下 Maven 命令:

    mvn site-deploy
    
    

它是如何工作的...

当运行 site-deploy 目标时,Maven 首先构建网站。然后,它使用 distributionManagement 元素中的条目集来确定网站需要如何部署。URL 的前一部分是要使用的传输协议。在这种情况下,它是 scp。它使用 settings.xml 文件中指定的凭据并将文件传输到目标位置。

更多内容...

如果你想在部署前测试你的网站,你可以轻松地按照以下方式操作:

  1. 运行以下 Maven 命令:

    mvn site:run
    
    
  2. 打开浏览器并访问 http://localhost:8080更多内容...

Maven Site 插件的运行目标会在一个 jetty 服务器上部署网站,默认情况下,它通过端口 8080 启动。这允许你在发布之前查看网站报告并验证它。

第八章. 处理典型构建需求

在本章中,我们将介绍以下食谱:

  • 包含和排除额外资源

  • 包含和排除源文件和文件夹

  • 配置 Maven 以搜索插件

  • 在离线模式下工作

  • 控制 Maven 输出的详细程度

  • 使用 Maven Help 插件

  • 使用 Maven SCM 插件

  • 为网站生成变更日志

简介

在前面的章节中,我们看到了如何设置 Apache Maven 来构建软件项目。我们也看到了如何配置它来分析代码质量和代码覆盖率。我们看到了如何生成和发布项目文档。

由于我们使用 Apache Maven,我们可能会遇到既不通用又不罕见的需求。在许多项目中,可能需要包含额外的源或资源文件夹。我们将看到 Maven 如何允许我们做到这一点。我们还想从 Maven 获得更多详细的输出,以便在出错时进行故障排除。我们还将看到在不使用互联网的情况下,我们可以将 Maven 构建工作到什么程度。我们还将看到 Maven 如何与软件配置管理SCM)系统协同工作,并允许 SCM 更改成为项目文档的一部分。

包含和排除额外资源

在编译或测试过程中,你可能会遇到需要包含额外的资源文件或文件夹的情况。你也可能需要排除特定的文件或文件夹。让我们看看我们如何做到这一点。

准备工作

Maven 已在你的系统上设置并验证了其工作。为此,请参考第一章的前三个食谱,入门

如何操作...

  1. 打开一个需要包含或排除文件或文件夹的 Maven 项目;例如,project-with-include-exclude

  2. 将以下内容添加到你的pom文件的build部分:

    <resources>
          <resource>
            <directory>src/resources/xml</directory>
            <includes>
              <include>*.xml</include>
            </includes>
          </resource>
          <resource>
            <directory>src/resources/json</directory>
            <includes>
              <include>include.json</include>
            </includes>
            <excludes>
              <exclude>exclude.json</exclude>
            </excludes>
          </resource>
    </resources>
    
  3. 运行以下命令:

    mvn resources:resources
    
    
  4. 观察输出:

    [INFO] --- maven-resources-plugin:2.6:resources (default-cli) @ project-with-include-exclude ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 2 resources
    [INFO] Copying 1 resource
    [INFO] ------------------------------------------------------------------------
    
    
  5. 查看资源文件夹的内容:如何操作...

  6. 查看构建输出目录的内容:如何操作...

它是如何工作的...

Maven Resources 插件的resources目标会复制构建输出目录所需的所有资源。此目标绑定到process-resources阶段,它是default生命周期的一部分。

默认情况下,目标会复制src/main/resources的内容。当在pom文件中指定resources标签时,它会根据指定的includeexclude过滤器复制那里目录的内容。

在我们的特定示例中,我们做了三件事:

  • src/resources/xml文件夹中包含了所有 XML 文件

  • src/resources/json文件夹中包含一个特定的文件

  • src/resouces/json文件夹中排除了一个特定的文件

更多内容...

如果我们需要有选择地复制测试资源怎么办?为此,我们需要做以下事情:

  1. 在你的pom文件的build部分添加以下内容:

    <testResources>
      <testResource>
        <directory>src/resources/xml</directory>
        <includes>
          <include>*.xml</include>
        </includes>
      </testResource>
      <testResource>
        <directory>src/resources/json</directory>
        <includes>
          <include>include.json</include>
        </includes>
        <excludes>
          <exclude>exclude.json</exclude>
        </excludes>
      </testResource>
    </testResources>
    
  2. 运行以下命令:

    mvn resources:testResources
    
    
  3. 查看目标文件夹test-classes的内容:还有更多...

这将现在将指定的测试资源复制到测试输出目录(target/test-classes)。

我们看到resourcestestResources目标分别将资源复制到classestest-classes。如果我们需要将这些资源复制到特定的文件夹中,例如,将xml文件复制到xml文件夹,将json文件复制到json文件夹,怎么办?Build Helper Maven 插件的add-resourceadd-test-resource目标在这里提供帮助。

  1. 使用以下代码更新pom文件:

    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>build-helper-maven-plugin</artifactId>
      <version>1.9.1</version>
      <executions>
        <execution>
          <id>add-resource</id>
          <phase>generate-resources</phase>
          <goals>
            <goal>add-resource</goal>
          </goals>
          <configuration>
            <resources>
              <resource>
                <directory>src/resources/xml</directory>
                <targetPath>xml</targetPath>
              </resource>
              <resource>
                <directory>src/resources/json</directory>
                <targetPath>json</targetPath>
                  <includes>
                    <include>include.json</include>
                  </includes>
                  <excludes>
                    <exclude>exclude.json</exclude>
                  </excludes>
              </resource>
            </resources>
          </configuration>
        </execution>
      </executions>
    </plugin>
    
  2. 运行以下命令:

    mvn compile
    
    
  3. 现在检查target/classes文件夹。

您将看到带有相应内容的xmljson子文件夹。

包含和排除源文件和文件夹

根据 Maven 约定,所有项目源文件都应该在src文件夹中。然而,可能存在组织方式不同的遗留项目,并且可能有多个源文件夹。此外,在某些项目中,我们可能需要从wsdl2java等工具动态生成源代码。在这种情况下,Maven 需要知道这些额外的源文件夹。请注意,这样的项目可能在 IDE 中运行不佳。

如何操作...

使用以下步骤在您的 Maven 项目中包含和排除源文件和文件夹:

  1. 打开名为project-with-additional-source的 Maven 项目。

  2. pom文件中添加以下部分:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.9.1</version>
            <executions>
              <execution>
                <id>add-source</id>
                <phase>generate-sources</phase>
                <goals>
                  <goal>add-source</goal>
                </goals>
                <configuration>
                  <sources>
                    <source>src/main/source</source>
                  </sources>
                </configuration>
              </execution>
            </executions>
        </plugin>
    
  3. 运行以下命令:

    mvn compile
    
    
  4. 查看生成的输出:

    [INFO] --- build-helper-maven-plugin:1.9.1:add-source (add-source) @ project-with-additional-source ---
    [INFO] Source directory: C:\projects\apache-maven-cookbook\project-with-additional-source\src\main\source added.
    
    
  5. 查看目标文件夹target/classes如何操作...

工作原理...

我们有一个名为src/main/source的额外源文件夹。我们在构建辅助 Maven 插件的configuration部分指定了这一点。我们还把插件的add-source目标绑定到了default生命周期的generate-sources阶段。

作为default生命周期的组成部分,在compile目标之前,Maven 会运行generate-sources阶段。这调用了插件的add-source目标,它为编译添加了额外的文件夹及其内容。

以类似的方式,可以添加额外的测试文件夹到构建中。配置将与之前的案例相同,除了execution部分,它将如下所示:

         <execution>
            <id>add-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
              <goal>add-test-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>src/main/source</source>
              </sources>
            </configuration>
          </execution> 

我们指定了add-test-source目标而不是add-source,并将其绑定到generate-test-sources阶段。

还有更多...

Build Helper Maven 插件提供了一些满足特定项目需求的其他目标。以下是一些例子:

  • attach-artifact:此功能用于附加额外的工件以安装和/或部署,除了项目工件。这可以通过以下方式配置插件:

          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.9.1</version>
            <executions>
              <execution>
                <id>attach-artifacts</id>
                <phase>package</phase>
                <goals>
                  <goal>attach-artifact</goal>
                </goals>
                <configuration>
                  <artifacts>
                    <artifact>
                      <file>some file</file>
                      <type>extension of your file </type>
                      <classifier>optional</classifier>
                    </artifact>
                  </artifacts>
                </configuration>
              </execution>
            </executions>
          </plugin>
    
  • maven-version:此功能用于设置包含当前 Maven 版本的属性,可以根据需要使用。为了在项目 JAR 的清单中使用 Maven 版本号,我们将配置插件如下:

      <build>
        <plugins>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.9.1</version>
            <executions>
              <execution>
                <id>maven-version</id>
                <goals>
                  <goal>maven-version</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.2</version>
            <configuration>
              <archive>
                <manifestEntries>
                  <Maven-Version>${maven.version}</Maven-Version>
                </manifestEntries>
              </archive>
            </configuration>
          </plugin>
        </plugins>
      </build>
    

配置 Maven 以搜索插件

你可能会记得,在关于使用 Maven JaCoCo 插件的章节中,为了生成代码覆盖率,我们必须从命令行显式指定插件的 projectIdartifactId 值。然而,对于大多数其他插件,我们只指定了插件名称而没有附加信息。

我们将看到为什么我们必须这样做以及如何避免它。

如何操作...

  1. 打开 settings 文件(具体来说是您家目录中的 settings.xml 文件)。

  2. 添加以下部分:

    <pluginGroups>
        <pluginGroup>org.jacoco</pluginGroup>
    </pluginGroups>
    
  3. 在之前运行 JaCoCo 的同一个项目上运行以下命令:

    mvn clean jacoco:prepare-agent test jacoco:report
    
    
  4. 观察输出:

    [INFO]
    [INFO] --- jacoco-maven-plugin:0.7.2.201409121644:report (default-cli) @ project-with-tests ---
    [INFO] Analyzed bundle 'Project with Tests' with 1 classes
    
    

它是如何工作的...

Maven 插件有两种类型,如下所示:

  • 由 Maven 团队本身维护的插件(让我们称它们为官方插件)。这些在默认插件组 org.apache.maven.pluginsorg.codehaus.mojo 中。

  • 所有其他插件(比如说第三方插件)。

所有官方插件都有相同的 groupId,即 org.apache.maven.plugins。它们还有一个关于 artifactId 的约定:maven-${prefix}-plugin,其中 prefix 代表插件前缀,是引用插件的简称。

用于引用插件的名称也可以自定义。前缀可以通过插件 pom 文件中的 Maven-plugin-plugingoalPrefix 配置参数直接指定。

因此,当我们运行 mvn clean 时,Maven 会搜索 org.apache.maven.plugins 组中的 maven-clean-plugin

第三方插件怎么办?pluginGroups 让 Maven 知道它应该在哪里搜索额外的插件。所以,在先前的例子中,Maven 在 org.jacoco 组中搜索插件。

第三方插件应该与官方插件有不同的名称。定义第三方插件的 artifactId 的传统方式是 ${prefix}-maven-plugin。当以这种方式指定时,Maven 会自动识别插件的快捷名称。在先前的例子中,由于 artifactIdjacoco-maven-plugin,快捷名称是 jacoco

还有更多...

在搜索以下默认组之前,Maven 总是会搜索指定的 pluginGroups

  • org.apache.maven.plugins

  • org.codehaus.mojo

Maven 会选择它找到的第一个快捷方式的匹配项。例如,如果在 pluginGroups 中的用户指定插件中有一个 clean 快捷方式,它将优先于 Maven Clean 插件。

离线模式工作

可能会有这样的情况,Maven 项目需要在没有互联网访问的情况下构建。让我们看看 Maven 如何支持这一点,以及需要注意的事项。

如何操作...

  1. 打开一个你想要离线构建的项目。

  2. 运行以下命令:

    mvn dependency:go-offline 
    
    
  3. 观察输出:如何操作...

  4. 运行以下命令:

    mvn –o clean package
    
    

注意到构建在没有网络连接的情况下成功完成。

它是如何工作的...

Maven Dependency 插件的 go-offline 目标根据 pom 文件下载项目所需的所有依赖和插件。–o 选项告诉 Maven 离线工作,不检查互联网上的任何内容。

然而,它并非没有问题。在一个全新的本地仓库中,offline 选项将无法使用,并出现以下错误:

如何操作...

这是 Maven Dependency 插件已知的问题或限制。必须在线构建所需的项目一次,以下载插件遗漏的任何内容。随后,项目可以离线构建。这通常不是必需的,因为大多数组织如果不允许直接访问互联网,会使用 Nexus 或 Artifactory 等仓库管理器。

小贴士

如果您的项目使用 SNAPSHOT 依赖项,那么 Maven 需要互联网来查找依赖项的更新。为了避免这种情况,您可以设置 updatePolicynever,但这将是适得其反的,因为您将无法获得依赖项的最新版本。

还有更多...

运行 Maven 的另一种离线模式是在 settings 文件中将 offline 参数指定为 true。一旦这样做,Maven 就不会尝试连接到互联网。

  1. 在设置文件中添加以下内容:

    <offline>true</offline>
    
  2. 运行 Maven 构建:

    mvn clean package
    
    

观察到构建成功完成,而没有连接到互联网。

控制 Maven 输出的详细程度

有时,Maven 的输出可能过于详细,我们可能只想看到错误。在其他时候,Maven 显示的信息可能不足,我们希望看到更多细节。让我们看看我们如何控制这一点。

如何操作...

  1. 打开一个 Maven 项目。

  2. 运行以下命令:

     mvn –q clean package 
    
    
  3. 观察输出:如何操作...

  4. 现在运行以下命令:

     mvn –X clean package 
    
    
  5. 观察输出:如何操作...

它是如何工作的...

Maven 提供了不同级别的日志记录。典型的级别是 DEBUG(详细消息)、INFO(信息消息)和 ERROR(错误消息)。指定一个级别将显示该级别及以上的所有消息。例如,指定 INFO 级别将显示 INFOERROR 级别的消息。

默认情况下,Maven 将所有 INFO 级别的消息记录到屏幕上。

-q 参数告诉 Maven 保持安静,不在屏幕上显示除 ERROR 级别消息之外的内容。因此,唯一显示的是测试输出。

另一方面,-X 参数告诉 Maven 显示所有 DEBUG 级别及以上的消息。这提供了大量信息,对于故障排除非常有用。

还有更多...

您可以将 Maven 输出重定向到文件以供稍后查看,而不是在屏幕上查看 Maven 输出。为此,运行以下命令:

 mvn –l simple-project-log.txt clean package

命令将在屏幕上无输出完成。simple-project-log.txt文件将包含所有日志消息。您可以使用-l-q-X结合,将适当的日志级别重定向到文件。

或者,可以将输出重定向到文件中:

mvn clean package > simple-project-log.txt

使用 Maven 帮助插件

Maven 提供了一个-h命令行标志来显示它支持的各个命令行参数。然而,还有一个帮助插件可以帮助您获取其他信息。

如何操作...

  1. 打开简单的 Maven 项目。

  2. 执行以下命令:

     mvn help:effective-pom 
    
    
  3. 观察输出结果:如何操作...

  4. 在具有配置文件的项目(例如,project-with-profile)上运行以下命令:

    mvn help:all-profiles
    
    
  5. 观察输出结果:

    [INFO] --- maven-help-plugin:2.2:all-profiles (default-cli) @ project-with-profile ---
    [INFO] Listing Profiles for Project: com.packt.cookbook:project-with-profile:jar
    :1.0-SNAPSHOT
     Profile Id: dev (Active: false , Source: pom)
    
    
  6. 执行以下命令:

    mvn –help:active-profiles
    
    
  7. 观察输出结果:

    Active Profiles for Project 'com.packt.cookbook:project-with-profile:jar:1.0-SNAPSHOT':
    
    The following profiles are active:
    
    
  8. 现在执行以下命令:

    mvn –Pdev help:active-profiles
    
    
  9. 观察输出结果:

    Active Profiles for Project 'com.packt.cookbook:project-with-profile:jar:1.0-SNAPSHOT':
    
    The following profiles are active:
    
     - dev (source: com.packt.cookbook:project-with-profile:1.0-SNAPSHOT)
    
    

以下是工作原理...

Maven 帮助插件提供不同的目标。这些也由 IDE 支持,如下所示:

  • effective-pom:这显示了在应用继承、插值和配置文件后,Maven 将使用的 pom 文件。当需要用于故障排除时,了解最终的 pom 文件是有用的。

  • all-profiles:此目标显示项目可用的所有配置文件。它指示配置文件是否处于活动状态。

  • active-profiles:此目标显示活动配置文件的列表。我们明确启用了dev配置文件(默认情况下不是活动的),因此它出现在活动配置文件列表中。

还有更多...

Maven 帮助插件还提供了一些其他目标。其中一个值得注意的是describe目标,它用于获取任何插件的详细信息。

  1. 为了理解这一点,让我们使用一个实例并运行以下命令:

    mvn help:describe -DgroupId=org.jacoco -DartifactId=jacoco-maven-plugin -Ddetail=true
    
    
  2. 观察结果:还有更多...

小贴士

describe目标不需要您有一个 Maven 项目。您只是为特定插件获取一些帮助信息!

使用 Maven SCM 插件

Maven 提供了一种以供应商无关的方式与 SCM 系统交互的机制。通常,Maven 项目被检查到 SCM 中。使用 Maven SCM 插件,您可以执行许多与 SCM 相关的活动。

准备工作

我们想要使用插件进行操作的 Maven 项目应该在 SCM 中。Maven 支持许多 SCM 提供商。我们将使用 Git 来演示这一点。

如何操作...

  1. 将以下代码添加到您的 pom 文件中:

      <scm>
            <connection>scm:git:https://bitbucket.org/maruhgar/apache-maven-cookbook</connection>
         <developerConnection>scm:git:https://maruhgar@bitbucket.org/maruhgar/apache-maven-cookbook</developerConnection>
            <url>https://bitbucket.org/maruhgar/apache-maven-cookbook</url>
        </scm>
    
  2. 执行以下命令:

    mvn scm:status
    
    
  3. 在 Windows 中观察输出结果:如何操作...

  4. 对于 Linux,输出结果如下:如何操作...

以下是工作原理...

当运行 Maven SCM 插件的status目标时,它会使用pom文件中scm标签中的信息来获取 SCM 详细信息。它使用这些信息并调用相应的scm命令来获取状态信息。在上面的示例中,它是git status

小贴士

相关 SCM 客户端的命令行版本必须安装并可在 Maven 路径中可用,以便此操作生效。

scm 标签中有三个条目:

  • connection:这是访问仓库的连接信息。这通常以下列形式存在:

    <service name>:<scm implementation>:<repository url>
    
    • service name:这将是一个版本控制系统。

    • scm implementation:这将是一个受支持的版本控制系统。

    • repository url:这将是一个仓库的 URL。

  • developerConnection:这与任何连接类似,但可能需要认证或具有额外的权限。通常,connection 访问会是只读的,而 developerConnection 访问会是读写。

  • url:这是仓库的 URL。

你也会注意到根据操作系统使用适当的 shell 命令,在 Windows 的情况下是 cmd.exe,而在 Linux 的情况下是 sh

更多...

Maven SCM 插件提供了许多其他命令,用于执行各种版本控制操作,例如 addremovecheckincheckoutupdatediffbranchtag

Bootstrap 是一个有趣的选项,可以用来检出并构建一个项目:

  1. 创建一个新的 Maven 项目(或打开 bootstrap-project 文件)。

  2. scm 部分添加一个有效的 Maven 项目:

    <scm>
        <connection>scm:git:https://github.com/maruhgar/mvn-examples</connection>
        <url>https://github.com/maruhgar/mvn-examples</url>
      </scm>
    
  3. build 部分添加以下条目:

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-scm-plugin</artifactId>
          <version>1.9.2</version>
          <configuration>
            <goals>install</goals>
            <goalsDirectory>test-properties</goalsDirectory>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
  4. 运行 Maven 命令:

    mvn scm:bootstrap
    
    
  5. 观察结果:更多...

我们的 Maven 项目已经检查了另一个 Maven 项目,使用 scm 部分中的信息,并在该上运行指定的目标。我们指定一个 goalsDirectory 元素,因为版本控制系统中包含多个项目,而我们只想为特定的项目执行目标,在这个例子中是 test-properties

为网站生成变更日志。

现在我们已经看到了 Maven SCM 插件的实际应用,我们可以看到如何使用这个特性来生成项目变更日志作为网站报告的一部分。

如何操作...

  1. 打开 Maven 项目 project-with-documentation

  2. reporting 部分添加以下条目:

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-changelog-plugin</artifactId>
            <version>2.3</version>
          </plugin>
    
  3. 运行以下命令:

    mvn site
    
    
  4. 观察输出:

    [INFO] Generating "Change Log" report    --- maven-changelog-plugin:2.3
    [INFO] Generating changed sets xml to: C:\projects\apache-maven-cookbook\project-with-documentation\target\changelog.xml
    [INFO] Executing: cmd.exe /X /C "git whatchanged "--since=2014-11-06 02:45:57 +0
    000" "--until=2014-12-07 02:45:57 +0000" --date=iso -- C:\projects\apache-maven-cookbook\project-with-documentation"
    
    
  5. 观察生成的报告:如何操作...

它是如何工作的...

当运行 site 命令时,Maven 使用 pom 文件中 reporting 部分的信息来生成各种报告。它找到一个 Maven Changelog 插件的条目,并生成相应的变更日志报告。

这实际上是项目的版本控制日志,包含如时间戳、作者和变更详情等信息。

第九章:多模块项目

在本章中,我们将介绍以下食谱:

  • 理解项目继承

  • 理解项目聚合

  • 结合继承和聚合

  • 执行多模块依赖项管理

  • 执行多模块插件管理

  • 选择性构建模块

  • 多模块项目的报告

简介

除了简单的项目外,大多数现实生活中的项目都有多个模块。每个模块都可以独立开发。一些模块可能依赖于其他模块。使用这些模块的项目希望确保它能够使用所有模块的正确版本成功构建。

当我们查看多个模块时,每个模块可能都会使用多个依赖项。为了避免依赖地狱,确保每个模块使用的依赖项版本得到良好管理非常重要。还有机会优化依赖项和插件,以减少构建脚本的重复。

理解项目继承

有时候,你可能希望项目使用另一个.pom文件中的值。你可能正在构建一个大型软件产品,因此不希望多次重复依赖项和其他元素。

Maven 为此提供了一个名为项目继承的功能。Maven 允许将父 POM 文件中指定的多个元素合并到继承的项目中。实际上,超级 POM 文件就是项目继承的一个例子。

准备工作

Maven 已在你的系统上设置并验证其工作。要这样做,请参阅第一章, 入门

如何做到这一点...

  1. 打开一个具有继承关系的项目;在我们的例子中是project-with-inheritance。这个项目有一个名为child的子文件夹,它是从父项目继承的项目。

  2. 按照以下方式更新父 POM 文件:

        <groupId>com.packt.cookbook</groupId>
        <artifactId>project-with-inheritance</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
    
  3. 按照以下方式为child创建 POM 文件:

      <parent>
          <groupId>com.packt.cookbook</groupId>
          <artifactId>project-with-inheritance</artifactId>
          <version>1.0-SNAPSHOT</version>
      </parent>
      <modelVersion>4.0.0</modelVersion>
      <artifactId>child</artifactId>
      <packaging>jar</packaging>
      <name>Child Project</name>
    
  4. child子文件夹中运行以下 Maven 命令:

    mvn clean package
    
    
  5. 观察输出:如何做到这一点...

它是如何工作的...

我们在child的 POM 文件中指定了一个parent元素。在这里,我们添加了父项目的坐标,即groupIdartifactIdversion。我们没有指定child项目的groupIdversion坐标。我们也没有指定任何propertiesdependencies

在父 POM 文件中,我们指定了propertiesdependencies

由于定义的关系,当 Maven 在child项目上运行时,它会继承父项目中定义的groupIdversionpropertiesdependencies

有趣的是,父 POM 文件(project-with-inheritance)对存在child项目的事实一无所知。

然而,这仅当父项目是pom类型时才有效。

Maven 是如何知道父 POM 的位置的?我们没有在 POM 文件中指定位置。这是因为,默认情况下,Maven 会在child的父文件夹中查找父 POM。否则,它会尝试从仓库下载父 POM。

还有更多...

如果父 pom 文件不在任何仓库中呢?如果它在子项目的父文件夹之外的不同文件夹中呢?让我们看看会发生什么:

  1. 打开一个子项目,其中父项目不在 parent 文件夹中,而是在一个子文件夹中(在我们的例子中,是 parent):还有更多...

  2. 按照以下方式更新子项目的 pom 文件:

      <parent>
          <groupId>com.packt.cookbook</groupId>
          <artifactId>parent</artifactId>
          <version>1.0-SNAPSHOT</version>
          <relativePath>../parent/pom.xml</relativePath>
     </parent> 
    
  3. 构建子项目:

    mvn clean package
    
    

Maven 现在通过 relativePath 元素确定父 pom 文件的位置,这表明了父 pom 文件所在的文件夹。使用这个信息,它成功地构建了子项目。

理解项目聚合

继承和聚合之间的一个关键区别在于,聚合是通过自上而下的方法定义的,而继承则是相反的方式。在 Maven 中,项目聚合类似于项目继承,只是更改是在父 pom 文件中进行的,而不是在子 pom 文件中。

Maven 使用术语 模块 来定义一个子项目或子项目,它是更大项目的一部分。一个聚合项目可以一起构建所有模块。此外,在父 pom 文件或聚合项目的 pom 文件上运行的 Maven 命令也将适用于它包含的所有模块。

如何操作...

  1. 打开一个具有聚合的项目;在我们的例子中是 project-with-aggregation。这个项目有一个名为 aggregate-child 的子文件夹,它是被父项目聚合的模块。

  2. 按照以下方式更新父 pom 文件:

        <groupId>com.packt.cookbook</groupId>
        <artifactId>project-with-aggregation</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
    
  3. 添加 module 部分,并指定子项目:

       <modules>
          <module>aggregate-child</module>
       </module>
    
  4. parent 文件夹中运行以下 Maven 命令:

    mvn clean package
    
    
  5. 观察输出:

    C:\projects\apache-maven-cookbook\project-with-aggregation>mvn clean package
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Build Order:
    [INFO]
    [INFO] Aggregate child Project
    [INFO] project-with-aggregation
    …
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Summary:
    [INFO]
    [INFO] Child Project ...................................... SUCCESS [  2.866 s]
    [INFO] project-with-aggregation ........................... SUCCESS [  0.004 s]
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    
    

它是如何工作的...

我们在聚合 pom 文件中将 child 项目指定为模块。子项目是一个正常的 Maven 项目,它没有关于存在聚合 pom 文件的信息。

当聚合项目构建时,它会依次构建子项目。你会在 Maven 输出中注意到 Reactor 这个词。Reactor 是 Maven 的一部分,它允许在一系列模块上执行目标。虽然模块是离散的工作单元;但可以使用 reactor 将它们聚集在一起同时构建。Reactor 根据每个模块声明的依赖关系确定正确的构建顺序。

还有更多...

就像继承的情况一样,模块不是聚合项目的子文件夹,而是一个同级文件夹。

  1. 按照以下方式更新 module 部分:

      <modules>
          <module>../aggregate-child</module>
       </module>
    
    
  2. 构建聚合项目:

    mvn clean package
    
    

Maven 现在通过指定的路径确定模块的位置,这表明了父 pom 文件所在的文件夹。按照惯例,模块名称应与文件夹名称相同。

结合继承和聚合

通过使用 Maven 的项目继承功能,我们可以在所有子项目中共享公共构建属性,如 propertiesdependencies。我们还可以聚合模块并将它们一起构建。

当使用项目继承时,父项目不会意识到子项目。在项目聚合的情况下,每个模块都不会意识到聚合。

我们现在将看到如何结合两者并获取其好处。

如何操作...

  1. 打开一个多模块项目;在我们的例子中,simple-multi-module。这个项目有一个子文件夹child,它是被父项目聚合的模块。

  2. 按照以下方式更新父 pom:

        <groupId>com.packt.cookbook</groupId>
        <artifactId>simple-multi-module</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
    
  3. 添加module部分并指定子项目:

       <modules>
          <module>child</module>
    
  4. 更新子 pom 以指定parent元素:

        <parent>
          <groupId>com.packt.cookbook</groupId>
          <artifactId>simple-multi-module</artifactId>
          <version>1.0-SNAPSHOT</version>
         </parent>
    
  5. 在父文件夹中运行以下 Maven 命令:

    mvn clean package
    
    
  6. 观察输出:

    [INFO] Reactor Summary:
    [INFO]
    [INFO] simple-multi-module ................................ SUCCESS [  0.162 s]
    [INFO] Child Project ...................................... SUCCESS [  2.411 s]
    
    

它是如何工作的...

我们在child pom 中指定了parent元素,以指明父项目是谁。我们还在父 pom 中将child项目指定为一个模块。因此,这两种关系——继承和聚合——都被定义了。

当我们构建父项目时,它通过modules元素自动构建子项目。同时,子项目也可以独立构建。

还有更多...

子项目不一定是父项目的子文件夹。如果它在其他地方,就像我们在前面的菜谱中看到的那样,它可以如下所示:

  • relativePath:父元素的relativePath应指向父元素的正确位置

  • modulemodule元素应包含指向子项目的适当路径

执行多模块依赖项管理

依赖项管理是一种集中化依赖项信息的机制。当有一组项目(或模块)继承一个共同的父项目时,所有关于依赖项的信息都可以放在父 pom 中,项目可以对这些依赖项进行更简单的引用。这使得在多个项目之间维护依赖项变得容易,并减少了由于同一依赖项的多个版本而通常出现的问题。

如何操作...

  1. 打开一个多模块项目(simple-multi-module)。

  2. dependencyManagement部分添加对junit的依赖项:

    <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
          </dependency>
        </dependencies>
    </dependencyManagement>
    
  3. 按照以下方式更新子项目的dependencies部分:

    <dependencies>
         <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
         </dependency>
    </dependencies>
    
  4. 执行以下命令:

    mvn clean test
    
    

    确保构建过程成功完成。

  5. 运行 Maven 命令以检查依赖项:

    mvn dependency:tree
    
    
  6. 观察结果:

    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ simple-multi-module
    ---
    [INFO] com.packt.cookbook:simple-multi-module:pom:1.0-SNAPSHOT
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Child Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ child ---
    [INFO] com.packt.cookbook:child:jar:1.0-SNAPSHOT
    [INFO] \- junit:junit:jar:3.8.1:test
    
    

它是如何工作的...

在父 pom 的dependencyManagement部分指定的依赖项对所有子项目都是可用的。子项目需要通过在dependencies部分显式指定所需的依赖项来选择依赖项。在此过程中,子项目可以省略versionscope信息,以便从父项目继承。

你可能会问:“为什么还要有dependencyManagement部分,子项目已经继承了父 pom 中定义的依赖项?”原因在于,父项目集中管理多个项目的依赖项。子项目通常只需要父项目定义的一些依赖项,而不是全部。dependencyManagement部分允许子项目有选择性地选择这些依赖项。

还有更多...

dependencyManagement部分也有助于解决 Maven 依赖调解的任何意外。依赖调解是确定在遇到多个版本的工件时将使用哪个版本的过程。然而,dependencyManagement优先于依赖调解,并确保依赖调解不会选择dependencyManagement中指定的版本之外的版本。

应该注意的是,不同版本的依赖项容易出错,dependencyManagement并不能总是避免库版本不兼容的问题。

执行多模块插件管理

在多模块项目中,pluginManagement允许你配置子项目所需使用的插件信息。父 pom 可以定义不同子项目使用的各种插件的配置。每个子项目可以选择它构建所需的插件。

如何操作...

  1. 打开一个多模块项目(simple-multi-module)。

  2. 在父 pom 的pluginManagement部分添加 Maven 构建辅助插件的配置,以复制额外的资源:

       <pluginManagement>
         <plugins>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.9.1</version>
            <executions>
              <execution>
                <id>add-resource</id>
                <phase>generate-resources</phase>
                <goals>
                  <goal>add-resource</goal>
                </goals>
                <configuration>
                  <resources>
                    <resource>
                      <directory>src/resources/xml</directory>
                      <targetPath>xml</targetPath>
                    </resource>
                    <resource>
                      <directory>src/resources/json</directory>
                      <targetPath>json</targetPath>
                        <includes>
                          <include>include.json</include>
                        </includes>
                        <excludes>
                          <exclude>exclude.json</exclude>
                        </excludes>
                    </resource>
                  </resources>
                </configuration>
              </execution>
            </executions>
          </plugin>
         </plugins>
        </pluginManagement>
      </build>
    
  3. 运行以下命令来构建项目:

     mvn clean test 
    
    

    注意,额外的资源没有被复制到子项目中。

  4. 现在,在子项目中使用相应的插件:

        <build>
           <plugins>
               <plugin>
                   <groupId>org.codehaus.mojo</groupId>
                   <artifactId>build-helper-maven-plugin</artifactId>
               </plugin>
           </plugins>
       </build>
    
  5. 再次构建项目。

  6. 观察输出:

    [INFO] Copying 2 resources to xml
    [INFO] Copying 1 resource to json
    
    

它是如何工作的...

我们在父 pom 的pluginManagement部分定义了 Maven 构建辅助插件,用于从额外的文件夹中复制资源。直到子项目使用该插件之前,它对子 pom 不可用。当子项目没有定义插件时,父 pom 中的插件定义没有效果。当子项目定义了插件时,它生效,并且额外的资源被复制过来。

还有更多...

如果插件是构建生命周期的一部分,那么即使在子项目中没有明确定义,pluginManagement部分的配置也会生效。让我们看看这是如何发生的:

  1. 在父 pom 的pluginManagement中定义 Maven 编译插件:

      <pluginManagement>
          <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
                </configuration>
            </plugin>
          <plugin>
    </pluginManagement>
    
  2. 不将插件添加到子 pom 中,使用 Java 7 运行以下命令:

    mvn clean test
    
    
  3. 观察错误:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.
    2:compile (default-compile) on project child: Fatal error compiling: invalid tar
    get release: 1.8 -> [Help 1]
    
    

这里发生了什么?尽管子 pom 没有定义 Maven Compiler 插件,但由于compile目标属于构建生命周期的一部分,父 pom 中pluginManagement部分的 Maven Compiler 插件配置仍然生效。由于配置指定了 Java 8 目标,编译失败。

如果我们不想继承特定的插件配置怎么办?Maven 提供了一种方法来实现这一点。让我们看看如何:

  1. 更新前面的 Maven 编译器插件配置如下:

      <pluginManagement>
          <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <inherited>false</inherited>
                <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
                </configuration>
            </plugin>
          <plugin>
    </pluginManagement>
    
  2. 现在用 Java 7 运行以下命令:

    mvn clean package
    
    
  3. 注意,项目编译时没有错误,尽管插件配置指定了 Java 8。

这是因为配置没有被继承到子模块中,因为我们把inherited元素设置为false

选择性地构建模块

当一个项目有多个模块时,可能会有一些情况,我们可能想要选择性地构建模块。这种情况之一可能是模块可能只在特定的机器上运行。另一个原因可能是模块可能有长时间运行的测试,这些测试可能只在测试服务器上有意义。

让我们看看如何通过使用 Maven 的配置文件功能来选择性地构建模块。

如何操作...

  1. 打开一个包含两个模块(two-multi-module)的多模块项目,即common-onedev-two

  2. 在父 POM 中,将一个项目添加到modules部分:

      <modules>
          <module>common-one</module>
      </modules>
    
  3. 定义一个配置文件并包含两个模块:

    <profiles>
          <profile>
              <id>dev</id>
              <modules>
                  <module>common-one</module>
                  <module>dev-two</module>
              </modules>
          </profile>
      </profiles>
    
  4. 运行带有dev配置文件的 Maven 命令构建:

    mvn –P dev clean test
    
    
  5. 观察结果:如何操作...

  6. 运行 Maven 命令构建不带配置文件:

    mvn clean test
    
    
  7. 观察结果:如何操作...

它是如何工作的...

当你有多个模块,并且想要控制特定模块的构建时机时,最简单的方法是为它们定义特定的配置文件,并在每个配置文件中定义模块。在我们的例子中,我们创建了一个dev配置文件来构建两个模块,common-onedev-two。默认的 Maven 构建过程只构建common-one模块。

我们实现的是根据需要排除或跳过特定模块的构建。正如你所见,配置文件只能扩展模块列表,因此它实际上不能实现黑名单功能。

小贴士

同样,我们可以在配置文件中定义pluginManagementdependencyManagement,这样它们只对配置文件生效。

还有更多...

Maven 还提供了命令行选项来选择性地构建模块。以下是一些示例,基于two-multi-module Maven 项目:

  • -pl –projects:这是一个以逗号分隔的项目列表,用于指定要构建的项目。以下是一个示例:

    mvn clean package –pl common-one
    
    
  • –am:这代表--also-make。如果指定了项目列表,这将构建列表中所需的项目:

    mvn clean package –pl common-one –am 
    
    
  • –amd:这代表--also-make-dependants。这会构建依赖于列表中项目的项目(如果指定了项目列表):

    mvn clean package –pl common-one –amd
    
    
  • -rf:这代表–resume-from。这可以从特定的项目恢复构建(在多模块构建失败的情况下很有用):

    mvn –Pdev clean package –rf dev-two 
    
    

多模块项目的报告

当我们谈论为多模块项目生成站点报告时,我们指的是为项目的每个模块和父项目生成此报告。在多模块项目的站点报告的情况下,需要考虑几个因素。第一个是要测试父模块和模块之间的链接是否正确工作。另一个是要检查是否可以将某些站点报告聚合,而不是为每个模块单独报告。

如何操作...

  1. 打开一个包含两个模块的多模块项目(two-multi-module),一个和两个。

  2. 将以下命令添加到父 pom 的reporting部分中的checkstyle

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <version>2.13</version>
            <reportSets>
              <reportSet>
                <id>aggregate</id>
                <inherited>false</inherited>
                <reports>
                  <report>checkstyle-aggregate</report>
                </reports>
              </reportSet>
            </reportSets>
          </plugin>
    
  3. 运行以下命令生成站点报告:

    mvn test site
    
    
  4. 点击站点报告中Checkstyle链接:如何操作...

工作原理...

当为多模块项目运行site目标时,它除了生成父模块的站点报告外,还为所有模块生成站点报告。所有报告都是为每个模块单独生成的。然而,像 Checkstyle 这样的插件提供了一个选项,可以在项目的所有模块之间生成聚合报告。这使我们能够获得项目所有模块的 Checkstyle 违规的统一视图。

小贴士

其他报告插件,如 FindBugs、PMD 和 Cobertura 支持多模块报告。然而,并非所有这些插件都支持报告的聚合。允许聚合报告的其他报告插件包括 Javadocs 和 JXR。

更多内容...

尽管为多模块项目生成的站点报告包含了指向每个子模块的链接,但这些链接将无法正确工作,因为每个模块报告都在相应模块的target/site文件夹中。

让我们看看我们如何验证报告中的模块是否正确链接:

  1. 在父 pom 中添加distributionManagement部分:

    <distributionManagement>
        <site>
          <id>packt</id>
          <url>file:///C:/fullsite</url>
        </site>
      </distributionManagement>
    
  2. 运行以下命令生成站点报告:

    mvn test site
    
    
  3. 运行以下命令来准备站点:

    mvn site:stage –DstagingDirectory=C:/fullsite
    
    
  4. 打开文件夹:更多内容...

你会注意到,这两个模块的站点数据现在都是项目站点文件夹的子文件夹。打开fullsite的索引页面,我们可以导航到每个模块站点并确保链接正常工作:

更多内容...

第十章:使用 Maven 进行 Java 开发

在本章中,我们将介绍以下食谱:

  • 构建 JAR 项目

  • 生成可执行的 JAR

  • 生成源代码的 JAR

  • 生成测试类的 JAR

  • 构建 WAR 项目

  • 构建 EAR 项目

  • 构建 pom 项目

  • 使用 Jetty 运行 Web 项目

  • 使用 Tomcat 运行 Web 项目

简介

Maven 主要是一个用于 Java 项目的构建工具。Java 项目可以生成不同类型的二进制文件。通常,Java 项目的输出是一个 JAR 文件。对于 Web 应用程序,Java 类与其他类型的文件结合,可以生成 WAR 或 EAR 文件。Maven 提供插件和生命周期阶段,用于为 Java 项目生成各种类型的二进制工件。

构建 JAR 项目

Maven 默认生成的工件类型是 JAR。如果 packaging 元素不存在,或指定为 jar,Maven 则将其视为 JAR 项目。JAR 项目将所有源代码以及必要的项目资源合并到一个文件中。这个 JAR 文件可以分发到其他地方使用。

准备工作

Maven 已在您的系统上设置并验证了其工作。要完成此操作,请参阅 第一章,入门

如何操作...

  1. 打开一个简单的 Maven 项目,在我们的例子中是 simple-project

  2. 验证类型是否存在或设置为 jar

      <modelVersion>4.0.0</modelVersion>
      <groupId>com.packt.cookbook</groupId>
      <artifactId>simple-project</artifactId>
      <packaging>jar</packaging>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出:

    [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ simple-project ---
    [INFO] Building jar: C:\Users\Deepa\Documents\apache-maven-cookbook\simple-project\target\simple-project-1.0-SNAPSHOT.jar
    
    

它是如何工作的...

package 选项是 Maven 默认生命周期的一部分。当 Maven 使用 package 选项运行时,它会按顺序运行到该选项之前和之前的所有阶段。Maven 首先编译项目,运行测试,然后根据打包类型,调用合适的插件进行打包。在我们的例子中,因为我们指定了打包为 jar,所以 Maven 使用 Maven JAR 插件的 jar 目标在 target 文件夹中创建 JAR 工件。

相关内容

  • 本章中的 生成可执行的 JAR 食谱

生成可执行的 JAR

Maven 生成的 JAR 工件在用作其他项目的依赖项时运行良好。然而,如果没有手动指定主类并明确指定项目在类路径中使用的依赖项,则不能作为可执行文件运行。

如果我们想为项目创建一个可执行的 JAR,这可能是有用的,当 JAR 需要测试或项目是一个简单的工具,应该无需额外努力即可调用时。

如何操作...

  1. 打开一个简单的 Maven 项目(project-with-executable-jar):

  2. pom 文件中添加以下部分:

    <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <archive>
                <manifest>
                  <addClasspath>true</addClasspath>
                  <mainClass>com.packt.cookbook.App</mainClass>
                </manifest>
              </archive>
            </configuration>
          </plugin>
        </plugins>
      </build>
    
  3. 将插件配置添加到 target 文件夹以复制依赖项:

    <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.9</version>
            <executions>
              <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                  <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                <outputDirectory>${project.build.directory}</outputDirectory>
                  <excludeArtifactIds>junit</excludeArtifactIds>
                </configuration>
              </execution>
            </executions>
          </plugin>
    
  4. 运行以下命令:

    mvn clean package
    
    
  5. 观察目标文件夹:如何操作...

  6. 运行生成的 JAR 文件:

     java -jar project-with-executable-jar-1.0-SNAPSHOT.jar
    
    
  7. 观察输出:

    C:\projects\apache-maven-cookbook\project-with-executable-jar\target>java -jar project-with-executable-jar-1.0-SNAPSHOT.jar
    06:40:18.437 [main] INFO  com.packt.cookbook.App - Hello World
    
    

它是如何工作的...

我们已经在 pom 文件中对 Maven JAR 插件进行了以下配置:

  • 添加类路径:这会将所有依赖的 JAR 添加到清单类路径部分

  • 指定了主类:此信息再次更新在清单中

我们还添加了 Maven Dependency 插件的copy-dependencies目标,将所需的依赖项复制到生成可执行 JAR 文件的文件夹中。

当我们运行可执行 JAR 时,它使用清单文件来确定主类以及依赖项,加载它们并运行。

让我们看看生成的清单文件:

它是如何工作的...

显然,为了使这可行,可执行 JAR 应该附带它所使用的依赖项。在第十一章“高级 Maven 使用”的创建一个 assembly 配方中,我们将学习如何创建包含所有依赖项的 assembly,这样就可以更容易地分发。

生成源代码的 JAR 文件

对于许多项目来说,生成源代码的 JAR 文件与工件一起非常有用。生成的源代码可以导入到 IDE 中,用于浏览和调试。通常,大多数开源项目的工件都附带源代码和 Javadocs。

如何操作...

  1. 打开你想要生成和附加源代码的项目(project-with-source-code)。

  2. 将以下插件配置添加到pom文件中:

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.4</version>
            <executions>
              <execution>
                <id>attach-sources</id>
                <phase>package</phase>
                <goals>
                  <goal>jar-no-fork</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出:

    [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ project-with-source-attached ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-source-attached\target\project-with-source-attached-1.0-SNAPSHOT.jar
    [INFO]
    [INFO] --- maven-source-plugin:2.4:jar-no-fork (attach-sources) @ project-with-source-attached ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-source-attached\target\project-with-source-attached-1.0-SNAPSHOT-sources.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] -----------------------------------------------------------------------
    
    
  5. 检查target文件夹:如何操作...

它是如何工作的...

我们将 Maven Source 插件添加到pom文件中。我们还配置了插件在打包阶段运行jar-no-fork目标。该目标创建项目源代码的 JAR 文件,并将其与项目工件一起提供。

jar-no-fork目标用于将目标绑定到构建生命周期。要独立于生命周期运行插件并创建 JAR,可以使用以下方式使用jar目标:

mvn source:jar

后续阶段(如install)将源工件与项目工件一起安装。

更多...

如果我们想附加 Javadoc 而不是(或与)源代码一起,让我们这样做:

  1. 将以下插件添加到pom文件中:

      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-javadoc-plugin</artifactId>
          <version>2.10.1</version>
          <executions>
            <execution>
              <id>attach-javadocs</id>
              <phase>package</phase>
              <goals>
                <goal>jar</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
    
  2. 构建聚合器项目:

    mvn clean package
    
    
  3. 观察输出:更多...

Maven 在运行 Maven Source 插件的jar-no-fork目标的同时,还运行 Maven Javadoc 插件的jar目标。现在除了项目工件外,还创建了这两个 JAR 文件,并可供分发。

小贴士

除了源代码外,如果项目相关,还可以生成和附加测试源代码和测试 Javadocs。

生成测试类的 JAR 文件

可能存在这样的情况,你希望将一个项目的测试类和资源作为测试依赖项用于另一个项目。这在多模块项目中很常见,其中一个模块依赖于另一个模块。模块的测试类中可能包含可以在另一个模块中重用的实用代码。

实现这一点的其中一种方法是通过创建一个单独的项目来保存这些类。然而,这样做可能会很繁琐,也可能令人困惑。

Maven 提供了另一种实现方式。

如何操作...

  1. 打开一个你想为其创建测试 JAR 的项目(project-with-test-jar)。

  2. 将以下插件配置添加到pom文件中:

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.5</version>
            <executions>
              <execution>
                <goals>
                  <goal>test-jar</goal>
                </goals>
              </execution>
            </executions>
           </plugin>
        </plugins>
      </build>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出结果:

    [INFO] --- maven-jar-plugin:2.5:jar (default-jar) @ project-with-test-jar ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-test-jar\tar
    get\project-with-test-jar-1.0-SNAPSHOT.jar
    [INFO]
    [INFO] --- maven-jar-plugin:2.5:test-jar (default) @ project-with-test-jar ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-test-jar\tar
    get\project-with-test-jar-1.0-SNAPSHOT-tests.jar
    
    
  5. 检查target文件夹:如何操作...

它是如何工作的...

我们为 Maven JAR 插件指定了一个test-jar目标。这会让 Maven 生成一个测试类和资源的 JAR 文件。这个 JAR 文件可以与项目工件一起安装。它也可以在另一个项目中指定为依赖项,如下所示:

<dependencies>
  <dependency>
    <groupId>com.packt.cookbook</groupId>
    <artifactId>project-with-test-jar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <type>test-jar</type>
    <scope>test</scope>
  </dependency>
</dependencies>

小贴士

需要注意的一点是,如果你在这个依赖项上添加了依赖,测试 JAR 不会带其传递的测试范围依赖项。如果需要,这些依赖项需要手动指定。

构建 WAR 项目

到目前为止,我们一直在构建生成 JAR 工件的项目。当涉及到 Web 应用时,我们通常创建 WAR 工件。Maven 支持 WAR 工件的构建。打包类型.war指示 Maven 这是一个 WAR 工件。Maven 会自动调用相应的生命周期绑定。

如何操作...

  1. 从命令提示符运行以下命令:

    mvn archetype:generate –DinteractiveMode=false  -DgroupId=com.packt.cookbook -DartifactId=simple-webapp -DarchetypeArtifactId=maven-archetype-webapp 
    
    
  2. 观察输出结果:如何操作...

  3. 打开创建的pom文件:

    <modelVersion>4.0.0</modelVersion>
      <groupId>com.packt.cookbook</groupId>
      <artifactId>simple-webapp</artifactId>
      <packaging>war</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>simple-webapp Maven Webapp</name>
      <url>http://maven.apache.org</url>
      <build>
        <finalName>simple-webapp</finalName>
      </build>
    
  4. 运行命令来构建项目:

    mvn clean package
    
    
  5. 观察输出结果:如何操作...

  6. 检查target文件夹:

    Directory of C:\projects\apache-maven-cookbook\simple-webapp\target
    
    18-12-2014  20:52    <DIR>          .
    18-12-2014  20:52    <DIR>          ..
    18-12-2014  20:52    <DIR>          classes
    18-12-2014  20:52    <DIR>          maven-archiver
    18-12-2014  20:52    <DIR>          simple-webapp
    18-12-2014  20:52             2,226 simple-webapp.war
    

它是如何工作的...

我们使用 Maven Archetype 插件来启动一个简单的 Web 项目。这生成了一个pom文件以及其他 Web 应用的文件内容。当你检查pom文件时,你会注意到packaging类型被设置为war

Maven 使用这些信息来调用 Maven 插件的war目标,以创建项目内容的 WAR 文件。

此外,请注意我们指定了finalName元素。Maven 使用这个元素来创建 WAR 工件的名称。如果没有这个元素,Maven 将使用默认名称,即simple-webapp-1.0-SNAPSHOT.war

还有更多...

Maven WAR 插件可以用多种方式使用。默认选项创建一个 WAR 文件。在开发过程中,我们可能希望通过生成展开形式的 WAR 文件来加快速度。为此,执行以下步骤:

  1. 打开simple-webapp项目。

  2. 运行以下命令:

    mvn war:exploded
    
    
  3. 检查target文件夹的内容:![还有更多...# 构建 EAR 项目 Maven 提供了生成 Java EE 企业存档EAR)文件的支持。这些可以在 JBoss、WebLogic 和 WebSphere 等应用服务器上部署。## 如何操作...1. 从命令提示符运行以下命令: java mvn archetype:generate -DgroupId=com.packt.cookbook -DartifactId=simple-ear -DarchetypeArtifactId=wildfly-javaee7-webapp-ear-archetype -DarchetypeGroupId=org.wildfly.archetype -DinteractiveMode=false 1. 观察结果:如何操作...

  4. 构建生成的项目:

    mvn clean package
    
    
  5. 观察生成的输出结果:如何操作...

  6. 打开 target 文件夹:如何操作...

它是如何工作的...

我们使用了 Maven 架构插件来启动一个简单的 EAR 项目。它生成一个多模块项目,其中包括一个 EJB 模块、Web 模块和一个 EAR 模块,以及一个聚合 pom 文件。当你检查 EAR 模块的 pom 文件时,你会注意到 packaging 类型被设置为 ear

一旦构建完成,Maven 会构建所有模块。在 EAR 模块中,它使用打包信息来调用 Maven EAR 插件的 ear 目标,以创建项目内容的 EAR。

构建 pom 项目

你可能想要将 pom 文件作为艺术品提供的许多原因之一是聚合项目。聚合项目必须具有 pom 打包类型。另一个原因可能是可以作为一个依赖项导入的 pom。无论原因如何,Maven 都提供了构建 pom 项目的支持。

如何操作...

  1. 打开一个简单的 pom 项目(simple-pom-project)。

  2. 观察打包类型:

    <groupId>com.packt.cookbook</groupId>
        <artifactId>simple-pom-project</artifactId>
        <packaging>pom</packaging>
        <version>1.0-SNAPSHOT</version>
        <description>Simple pom project</description>
    
  3. 构建项目:

    mvn clean package
    
    

    注意,只有 clean 目标被运行。

  4. 运行以下命令:

     mvn clean install 
    
    
  5. 观察输出:如何操作...

它是如何工作的...

以下是 pom 打包类型的默认绑定:

  • package: site:attach-descriptor:如果适用,这会将描述符附加到站点报告中

  • install: install:install:这会在本地仓库中安装项目

  • deploy: deploy:deploy:这会将项目部署到远程仓库

如我们所见,Maven 不会为 pom 打包类型运行任何其他目标。然而,如果它看到 module 元素,它会在所有定义的模块上调用指定的 Maven 目标。

此外,包括 pluginManagementdependencyManagement 在内的各种配置都会被所有子项目继承。

还有更多...

如果你有一个原因需要编译一些源文件或运行一些测试,即使打包类型是 pom,怎么办?这可能不是一个常见的场景,但可以通过以下方式显式调用相关插件目标来完成:

  1. 打开简单的 pom 项目(simple-pom-project)。

  2. 运行以下命令:

    mvn clean compiler:compile compiler:testCompile surefire:test jar:jar
    
    
  3. 观察输出:还有更多...

我们现在显式调用以下目标:

  • compiler:compile:这会编译源文件

  • compiler:testCompile:这会编译测试文件

  • surefire:test:这会运行测试

  • jar:jar:这会创建一个 JAR 艺术品

Maven 并不会阻止我们这样做。

使用 Jetty 运行 Web 项目

在开发 Web 应用程序时,有一个快速的方法来检查应用程序是否成功部署且没有错误是很不错的。IDE 允许用户进行热部署应用程序。Maven 提供了一种机制,可以使用 Jetty 快速运行项目。Jetty 是一个流行的开源应用程序服务器,可以用来部署 Web 项目。Maven Jetty 插件允许将应用程序部署到 Jetty,并在 Maven 构建过程中运行它们。

如何操作...

  1. 打开一个简单的 Web 项目(simple-web-project)。

  2. 运行以下 Maven 命令:

    mvn org.eclipse.jetty:jetty-maven-plugin:run
    
    
  3. 观察结果:如何操作...

  4. 通过访问 http://localhost:8080 从浏览器访问 Web 应用程序。![如何操作...]

它是如何工作的...

Maven Jetty 插件允许使用 Jetty 部署和测试 Web 应用程序。run 目标绑定到 package 阶段。Maven 运行它之前的所有阶段。Jetty 从其源代码部署 Web 应用程序;Web 应用程序不需要构建成 WAR 文件。它会在默认的 Maven 位置查找 Web 应用程序的相关部分。以下是一些示例:

  • src/main/webapp 中的 resources

  • target/classes 中的 classes

  • src/main/webapp/WEB-INF 中的 web.xml

Jetty 使用默认值启动服务器。

小贴士

由于 Jetty 不是一个官方的 Maven 插件,我们明确指定了 groupId (org.eclipse.jetty) 和 artifactId (jetty-maven-plugin),而不是短插件前缀。要使用短插件前缀,请在设置文件中添加以下内容:

<pluginGroup>org.eclipse.jetty</pluginGroup>

然后,可以按如下方式调用 Maven:

mvn jetty:run

还有更多...

Maven Jetty 插件提供了一些目标和配置,以帮助开发 Web 应用程序。

  1. 运行 WAR 文件:

    mvn jetty:run-war
    
    

    Jetty 现在构建 WAR 文件然后运行:

    还有更多...

  2. 运行展开的 WAR 文件:

    mvn jetty:run-exploded
    
    

    Jetty 现在构建 WAR 文件,将其展开,然后运行:

    还有更多...

还有一些其他的目标可以使用:

  • jetty:deploy-war: 这将部署现有的 WAR 文件而无需构建它

  • jetty:start: 这将启动 Jetty 服务器

  • jetty:stop: 这将停止 Jetty 服务器

  • jetty:run-forked: 这将在与 Maven 不同的 Java 虚拟机进程中运行 Jetty 服务器

使用 Tomcat 运行 Web 项目

Tomcat 是一个流行的开源应用程序服务器。Maven Tomcat 插件支持在 Tomcat 中构建和部署 Maven 项目。实际上,有两个 Maven Tomcat 插件,一个用于 Tomcat 6,另一个用于 Tomcat 7。

让我们看看如何使用 Tomcat 7 运行 Web 项目。步骤将与 Tomcat 6 相同,只是插件将是 tomcat6-maven-plugin 而不是 tomcat7-maven-plugin,插件前缀将是 tomcat6 而不是 tomcat7

如何操作...

  1. 打开一个简单的 Web 项目(simple-web-project)。

  2. 运行以下 Maven 命令:

    mvn org.apache.tomcat.maven:tomcat7-maven-plugin:run
    
    
  3. 观察结果:如何操作...

  4. 通过访问 http://localhost:8080/simple-webapp 浏览已部署的 Web 应用程序。![如何操作...]

它是如何工作的...

Maven Tomcat 插件允许使用 Apache Tomcat 部署和测试 Web 应用程序。run 目标绑定到 package 阶段。Maven 运行它之前的所有阶段。

Tomcat 使用默认值启动服务器。

小贴士

由于这不是官方的 Maven 插件,我们明确指定了 groupId (org.apache.tomcat.maven) 和 artifactId (tomcat7-maven-plugin),而不是使用简短的插件前缀。要使用简短的插件前缀,请在设置文件中添加以下内容:

<pluginGroup>org.apache.tomcat.maven</pluginGroup>

然后,可以按照以下方式调用 Maven:

mvn tomcat7:run

还有更多...

Maven Tomcat7 插件也支持启动和停止 Tomcat 的目标,这在运行集成测试时可以使用。

它还支持使用嵌入式 Tomcat 创建可执行 JAR 文件。让我们看看如何做:

  1. 打开您想要创建可执行 JAR 文件的 Web 项目(project-with-executable-webapp)。

  2. 添加以下插件和配置:

         <plugins>
           <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <executions>
              <execution>
                <id>tomcat-run</id>
                <goals>
                  <goal>exec-war-only</goal>
                </goals>
                <phase>package</phase>
                <configuration>
                  <path>/</path>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
    
  3. 运行以下命令:

    mvn clean package
    
    
  4. 运行 target 文件夹中创建的 JAR 文件:

    java –jar project-with-executable-webapp-1.0-SNAPSHOT-war-exec.jar
    
    
  5. 观察输出:还有更多...

我们现在有一个使用嵌入式 Tomcat 的可分发 Web 应用程序。

小贴士

由于存在一个错误,我们需要使用插件的 2.1 版本而不是 2.2 版本才能使其工作。

第十一章. 高级 Maven 使用

让我们看看本章中的以下食谱:

  • 创建汇编

  • 运行自定义的可执行文件

  • 运行 ANT 任务

  • 确定 Maven 插件的更新

  • 确定 Maven 依赖的更新

  • 控制约束

  • 生成唯一的构建

  • 发布 Maven 项目

简介

在本章中,我们探讨使用 Maven 的功能,这些功能可能不是在常规基础上或项目中必需的。这些功能包括为分发组装项目以及发布项目。这些不是典型的构建任务,但却是项目生命周期中的基本要素。

创建汇编

一个典型的项目需求是将项目输出及其依赖项、模块和其他文件聚合到一个可分发的存档中。汇编是一组文件、目录和依赖项,它们被组装成存档格式并分发。Maven 提供了预制汇编描述符来构建这些汇编。描述符处理常见的操作,例如打包项目的工件及其依赖项。

准备工作

Maven 应该已经设置在你的系统上,并且经过验证可以工作。为此,请参考 第一章, 入门

如何操作...

  1. 打开你想要生成汇编的 Maven 项目;在我们的例子中,是 project-with-assembly

  2. 将以下插件和配置添加到 pom 文件中:

    <plugin>
      <artifactId>maven-assembly-plugin</artifactId> 
      <version>2.5.3</version>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>com.packt.cookbook.App</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id> 
          <phase>package</phase> 
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出:

    [INFO] --- maven-assembly-plugin:2.5.3:single (make-assembly) @ project-with-assembly ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-assembly\target\project-with-assembly-1.0-SNAPSHOT-jar-with-dependencies.jar
    
    
  5. 运行创建的分布 JAR:

    C:\projects\apache-maven-cookbook\project-with-assembly\target>java -jar project-with-assembly-1.0-SNAPSHOT-jar-with-dependencies.jar
    07:13:25.660 [main] INFO  com.packt.cookbook.App - Hello World
    
    

它是如何工作的...

我们对 pom 文件做了以下更改:

  • 我们选择了 jar-with-dependencies,这是 Maven 汇编插件提供的预制汇编描述符之一。这创建了一个包含项目所有依赖的单个 JAR 文件。

  • 我们还使用了 archive 配置来指定项目的主类。这是为了使 JAR 文件可执行。

  • 我们指定了汇编的单个目标应该在哪个阶段运行,即 package 阶段。

当 Maven 运行时,它使用了前面的配置,在 package 阶段组装了一个包含依赖的 JAR 文件。我们可以将其作为一个正常的可执行 JAR 运行。

除了预定义的描述符之外,Maven 汇编插件还允许我们创建自定义描述符,可以精细控制汇编的内容。

汇编插件还可以从多模块项目构建汇编,其中模块可以是最终汇编的一部分。

更多内容...

当打开 JAR 文件时,你会观察到所有依赖的 JAR 文件也被解包了。

更多内容...

这是因为预定义描述符的默认配置。让我们看看如何创建相同的分发,但保留依赖的 JAR 文件不变。为此,我们现在将使用一个 Maven JAR 插件,该插件使用自定义类加载器在父 JAR 中加载依赖 JAR:

  1. 打开你想要创建具有未打包依赖 JAR 文件的可执行文件的项目(project-with-one-jar)。

  2. 在 pom 文件中添加以下插件:

        <plugin>
            <groupId>org.dstovall</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
            <executions>
              <execution>
                <id>make-assembly</id> 
                <phase>package</phase> 
                <goals>
                  <goal>one-jar</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
    
  3. 添加 JAR 插件以指定可执行 JAR 的主类:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
        <archive>
            <manifest>
                     <mainClass>com.packt.cookbook.App</mainClass>
            </manifest>
         </archive>
       </configuration>
    </plugin>
    
  4. 添加以下代码,因为插件二进制文件不在中央 Maven 仓库中:

        <pluginRepositories>
            <pluginRepository>
                <id>onejar-maven-plugin.googlecode.com</id>
                <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
            </pluginRepository>
       </pluginRepositories>
    
  5. 运行以下命令:

    mvn package
    
    
  6. 运行生成的可执行文件并观察结果:

    java -jar project-with-one-jar-1.0-SNAPSHOT.one-jar.jar
    06:57:45.995 [main] INFO  com.packt.cookbook.App - Hello World
    
    
  7. 打开创建的 JAR 文件:更多内容...

    我们可以看到,与 assembly JAR 相比,可执行 JAR 是在不解包涉及的库(依赖项)的情况下创建的。

  8. 导航到 JAR 中的lib文件夹:更多内容...

    依赖的 JAR 文件存储在lib文件夹中。

参考以下内容

  • 在第十章“使用 Maven 进行 Java 开发”中的生成可执行 JAR配方,使用 Maven 进行 Java 开发

运行自定义的可执行文件

有许多情况下,你希望 Maven 在你的计算机上运行特定的可执行文件。一个简单的用例就是运行你创建的 JAR 文件。另一个情况是让 Maven 运行不是作为插件提供的命令(例如,创建一个本地的 Windows 安装程序)。

Maven 提供了一种机制,可以在 Maven 运行的同一虚拟机上以单独的进程运行任何可执行的系统,同时与 Java 程序一起运行。Maven Exec 插件使用exec目标(在单独的进程中运行)和java目标(在同一进程中运行 Java 程序)提供这种支持。

如何操作...

  1. 打开一个简单的 Maven 项目(simple-project)。

  2. 运行以下命令:

    mvn clean package exec:java –Dexec.mainClass="com.packt.cookbook.App"
    
    
  3. 观察结果:如何操作...

它是如何工作的...

我们想在项目中运行我们创建的 JAR 文件。为此,我们调用了 Maven Exec 插件的java目标。我们向插件提供了所需的参数(mainClass),以便它知道需要运行哪个主类。

更多内容...

你可以将可执行文件的运行集成到项目生命周期中。让我们为我们的示例做这个:

  1. 打开项目(让我们称它为project-with-exec)。

  2. 将以下代码添加到 pom 文件中:

          <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>exec-maven-plugin</artifactId>
              <version>1.3.2</version>
              <executions>
                <execution>
                  <id>hello-world</id>
                  <phase>package</phase>
                  <goals>
                    <goal>java</goal>
                  </goals>
                </execution>
              </executions>
              <configuration>
                <mainClass>com.packt.cookbook.App</mainClass>
              </configuration>
            </plugin>
    
  3. 运行以下命令:

    mvn clean package
    
    
  4. 观察结果:

    [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ project-with-exec ---
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-exec\target\
    project-with-exec-1.0-SNAPSHOT.jar
    [INFO]
    [INFO] --- exec-maven-plugin:1.3.2:java (hello-world) @ project-with-exec ---
    [WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment
    on MEXEC-6.
    06:25:26.005 [com.packt.cookbook.App.main()] INFO  com.packt.cookbook.App - Hell
    o World
    [INFO] ------------------------------------------------------------------------
    
    

项目在包阶段根据我们在插件中指定的配置运行。

对于非 Java 可执行文件也可以这样做;我们需要调用exec目标而不是java目标。

小贴士

运行系统可执行文件会使构建不可移植,所以请谨慎使用。

运行一个 ANT 任务

ANT 是一个流行的构建自动化工具,它提供了很高的灵活性。它还提供了诸如echotouch之类的任务,这些任务在 Maven 中不可用。尽管如此,将 ANT 任务与 Maven 结合以实现某些目标可能是有利的,尽管最好在不可避免的情况下才这样做。

Maven 通过 Maven AntRun 插件提供了一种机制来运行任意的 ANT 任务。让我们看看如何使用它来在我们的项目中运行一个 ANT 任务。

如何操作...

  1. 打开你想要运行 ANT 任务的工程(project-with-ant)。

  2. 将以下插件配置添加到 pom 文件中:

         <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.8</version>
            <executions>
              <execution>
                <phase>package</phase>
                <configuration>
                  <target>
                      <echo message="Calling ant task in package phase"/>
                  </target>
                </configuration>
                <goals>
                  <goal>run</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出:如何做到这一点...

它是如何工作的...

我们配置了 Maven AntRun 插件在 package 阶段运行一个 ANT 目标。在 ANT 目标中,我们指定了一个简单的 echo 任务,它输出了我们想要的一个字符串。

我们可以写更复杂的任务,而不是 echo 任务。Maven AntRun 插件还提供了让 ANT 任务引用 Maven 属性、类路径等的方法。

还有更多...

将 ANT 任务分离到单独的 ANT 构建脚本(build.xml)中,并从 Maven 中调用它是一个好的做法。让我们看看如何做到这一点:

  1. 创建一个简单的 ANT 构建脚本,build.xml,并添加以下内容:

      <project name="project-with-ant" default="echo" basedir=".">
        <description>
            Simple ant task to echo a string
        </description>
    
        <target name="echo">
            <echo message="Hello World"/>
       </target>
    </project> 
    
  2. 将 pom 文件中的 target 配置替换如下:

    <target>
        <ant target="echo"/>
     </target>
    
  3. 运行以下 Maven 命令:

    mvn clean package
    
    
  4. 观察输出:还有更多...

结果相同,但现在 ANT 脚本已经与 Maven 分离。

确定 Maven 插件 AntRun 的更新

在我们的构建脚本中,我们明确指定了我们使用的 Maven 插件的版本。这是创建可重复构建所必需的。如果没有指定版本,Maven 会给出如下警告:

[WARNING] Some problems were encountered while building the effective model for
com.packt.cookbook:project-with-exec:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.codehaus.mojo:exec-maven-plugin is missing. @ line 42, column 17
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.

在一段时间内,这些插件可能会有更新。了解是否有任何更新以便我们可以相应地更新插件版本会很好。让我们看看如何做到这一点。

如何做到这一点...

  1. 选择你想要检查插件更新的工程(project-with-exec)。

  2. 将插件的版本更改为较旧的一个:

      <artifactId>exec-maven-plugin</artifactId>
       <version>1.2</version>>
    
  3. 运行以下命令:

    mvn versions:display-plugin-updates
    
    
  4. 观察输出:

    [INFO] --- versions-maven-plugin:2.0:display-plugin-updates (default-cli) @ proj
    ect-with-exec ---
    [INFO]
    [INFO] All plugins with a version specified are using the latest versions.
    ...
    [WARNING] The following plugins do not have their version specified:
    [WARNING]   maven-clean-plugin .......................... (from super-pom) 2.5
    [WARNING]   maven-compiler-plugin ....................... (from super-pom) 3.1
    ...
    [WARNING] Project does not define minimum Maven version, default is: 2.0
    [INFO] Plugins require minimum Maven version of: 2.2.1
    ...
    [ERROR] Project does not define required minimum version of Maven.
    [ERROR] Update the pom.xml to contain
    [ERROR]     <prerequisites>
    [ERROR]       <maven>2.2.1</maven>
    [ERROR]     </prerequisites>
    ...
    [INFO] Require Maven 2.2.1 to use the following plugin updates:
    [INFO]   maven-jar-plugin ................................................ 2.5
    [INFO]   maven-site-plugin ............................................... 3.2
    [INFO]   org.codehaus.mojo:exec-maven-plugin ........................... 1.3.2
    
    

它是如何工作的...

Maven Versions 插件的 display-plugin-updates 目标会下载 pom 文件中指定的所有插件的元数据,然后生成一个报告。报告揭示了若干有趣的事情。

  • prerequisites 标签缺失。在 pom 文件中的 prerequisites 标签指定了构建项目所需的 Maven 的最低版本。如果没有这个标签,Maven 会将最低版本视为 2.0。如果不同的开发者使用不同的 Maven 版本,则存在无法重复构建的风险。因此,使用此标签指定最低版本是一个好的做法。

  • 有关于插件版本未定义的警告。正如我们所见,pom 文件中的插件不需要明确指定,除非它们需要配置。现在,Maven 仍然使用各种插件来执行(如 clean、resources、compile、test 等),并且它需要确定要使用的版本。它使用 super pom 中指定的版本,这在大多数情况下是可行的。然而,Versions 插件提醒我们这种情况,因此我们可以采取适当的行动。

  • 根据 Maven 版本,插件版本存在差异。报告根据使用的 Maven 版本指定了各种插件的版本。这就是为什么指定先决条件的重要性更加凸显。

如输出所示,如果我们指定需要至少2.2.1版本的 Maven,那么我们可以看到 Maven Exec 插件的更新版本是1.3.2

还有更多...

让我们现在在 pom 文件中指定prerequisites元素,看看它如何影响目标输出:

  1. 将以下内容添加到 pom 文件中:

      <prerequisites>
        <maven>3.2.5</maven>
      </prerequisites>
    
  2. 运行以下命令:

    mvn versions:display-plugin-updates
    
    
  3. 观察输出:

    [INFO] --- versions-maven-plugin:2.0:display-plugin-updates (default-cli) @ project-with-exec ---
    ...
    [INFO]
    [INFO] The following plugin updates are available:
    [INFO]   org.codehaus.mojo:exec-maven-plugin .................... 1.2 -> 1.3.2
    [INFO]
    
    

我们现在可以看到,插件根据我们指定的先决条件报告插件更新。

确定我们未在 pom 文件中明确定义的插件是否有更新是困难的。例如,根据前面命令的输出,如下所示:

[WARNING] The following plugins do not have their version specified:
[WARNING]   maven-clean-plugin .......................... (from super-pom) 2.5
[WARNING]   maven-compiler-plugin ....................... (from super-pom) 3.1
[WARNING]   maven-deploy-plugin ......................... (from super-pom) 2.7
[WARNING]   maven-install-plugin ........................ (from super-pom) 2.4

然而,截至撰写本书时,Maven Clean 插件的最新版本是 2.6.1,Maven Compiler 插件的版本是 3.2,等等。super pom 中有的版本是在创建时必须是最新版本。当新版本中存在错误或新功能时,这些依赖项的版本变得很重要。在这种情况下,我们确实想要获取这些插件的最新版本。通过在 pom 文件中明确指定插件的版本,很容易获取这些版本。

将以下内容添加到 pom 文件中:

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-clean-plugin</artifactId>
          <version>2.5</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.1</version>
        </plugin>

现在,重新运行前面的命令并注意输出:

[INFO] The following plugin updates are available:
[INFO]   maven-clean-plugin ..................................... 2.5 -> 2.6.1
[INFO]   maven-compiler-plugin .................................... 3.1 -> 3.2
[INFO]   org.codehaus.mojo:exec-maven-plugin .................... 1.2 -> 1.3.2

确定 Maven 依赖项的更新

我们使用许多第三方库来构建我们的项目。如您所忆,我们在 pom 文件中指定了这些依赖库的groupIdartifactIdversion元素。在这些依赖库中,可能会有许多更新和版本发布的情况。有一个机制来通知这些发布并相应地更新项目构建文件将是很好的。

如何做到这一点...

  1. 选择一个你想要检查依赖项更新的项目,例如simple-project,这是我们使用 quick-start 存档创建的。

  2. 运行以下命令:

    mvn versions:display-dependency-updates
    
    
  3. 观察输出:

    [INFO] --- versions-maven-plugin:2.1:display-dependency-updates (default-cli) @
    simple-project ---
    [INFO] artifact junit:junit: checking for updates from central
    [INFO] The following dependencies in Dependencies have newer versions:
    [INFO]   junit:junit ............................................ 3.8.1 -> 4.12
    
    

它是如何工作的...

Maven Versions 插件的display-dependency-updates目标使用每个 maven 依赖项的元数据来确定每个依赖项的最新版本。如果不匹配当前版本,它将显示差异报告。

我们之前已经看到,SNAPSHOT版本由 Maven 以不同的方式处理,并且它会根据配置自动检查和更新这些依赖项。如果SNAPSHOT的版本号发生变化(从1.0-SNAPSHOT1.1-SNAPSHOT),那么 Versions 插件会指出这一点。

还有更多...

Maven Versions 插件提供了其他一些目标来管理依赖和插件版本的更新。这包括自动将版本更改为最新发布版本,将 SNAPSHOT 替换为发布版本等。

控制约束

构建工具的一个要求是能够生成可重复的构建。在一个项目中,构建工具应该对所有团队成员的行为保持一致。虽然可以制定关于要使用的 Java 或 Maven 版本的项目指南,但如果可以自动强制执行,那就更容易了。

正是 Maven Enforcer 插件发挥作用的地方。

如何实现...

  1. 打开一个简单的项目(project-with-enforcer)。

  2. 添加以下插件配置:

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>1.3.1</version>
            <executions>
              <execution>
                <id>enforce-versions</id>
                <goals>
                  <goal>enforce</goal>
                </goals>
                <configuration>
                  <rules>
                    <requireMavenVersion>
                      <version>3.2.3</version>
                    </requireMavenVersion>
                    <requireJavaVersion>
                      <version>1.8</version>
                    </requireJavaVersion>
                  </rules>
                </configuration>
              </execution>
            </executions>
          </plugin>
    
  3. 使用 Java 7 和 Maven 3.2.3 构建项目:

    mvn clean package.
    
    
  4. 观察输出:如何实现...

它是如何工作的...

Enforcer 插件使用规则配置并验证项目是否符合规则。如果发现违规,它会报告错误并停止构建。

在前面的例子中,我们的项目有两个问题:

  • Maven 版本:我们使用的是 3.2.3 版本,但在规则中指定了 3.2.5 版本。

  • Java 版本:我们使用的是 Java 7,但在规则中指定了 Java 8。

还有更多...

Maven Enforcer 插件有其他一些规则来强制执行各种约束。以下是一些例子:

  • requireOS:这确保项目只能在特定的操作系统上构建。

  • requireFilesExist:这确保了项目构建需要特定的文件存在。

也可以实现自定义执行规则。其中之一可在github.com/ferstl/pedantic-pom-enforcers找到。

生成唯一构建

正如我们所见,我们使用 SNAPSHOT 版本来指定项目处于开发状态。在开发过程中,我们将为项目创建几个构建。在许多情况下,区分这些构建是有用的。例如,当我们使用持续集成时,或者当测试人员需要对构建记录缺陷时。

如果有一种方法可以生成唯一的构建数字来识别 SNAPSHOT 版本中的构建,那就太好了。

如何实现...

  1. 打开你想要有构建数字的项目(project-with-build-number)。

  2. 添加以下插件配置:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>buildnumber-maven-plugin</artifactId>
            <version>1.3</version>
            <executions>
              <execution>
                <phase>validate</phase>
                <goals>
                  <goal>create</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
               <shortRevisionLength>5</shortRevisionLength>
            </configuration>
          </plugin>
    
  3. 添加以下内容以使用创建的唯一构建数字:

    <finalName>${project.artifactId}-${project.version}-r${buildNumber}</finalName>
    
  4. 为项目添加版本控制系统(SCM)配置:

    <scm>
         <developerConnection>scm:git:https://bitbucket.org/maruhgar/apache-maven-cookbook</developerConnection>
          <url>https://bitbucket.org/maruhgar/apache-maven-cookbook</url>
      </scm>
    
  5. 构建项目:

    mvn clean package
    
    
  6. 观察输出:

    [INFO] --- buildnumber-maven-plugin:1.3:create (default) @ project-with-build-nu
    mber ---
    [INFO] ShortRevision tag detected. The value is '5'.
    [INFO] Executing: cmd.exe /X /C "git rev-parse --verify --short=5 HEAD"
    [INFO] Working directory: C:\projects\apache-maven-cookbook\project-with-build-n
    umber
    [INFO] Storing buildNumber: 0950d at timestamp: 1421244408851
    [INFO] Storing buildScmBranch: master
    ...
    [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ project-with-build-number --
    -
    [INFO] Building jar: C:\projects\apache-maven-cookbook\project-with-build-number
    \target\project-with-build-number-1.0-SNAPSHOT-r0950d.jar
    
    

它是如何工作的...

Maven Build Number 插件提供了三种生成唯一数字的方法,即通过使用版本控制系统(SCM)、顺序构建数字或时间戳。

在前面的例子中,我们使用了版本控制系统,因为它很容易将构建映射到相应的版本控制系统版本。我们使用了 git 并在 pom 文件的 SCM 标签中指定了 SCM 详细信息。

我们还指定了 Maven Build Number 插件使用五个字符并创建短修订号,因为典型的 git 修订号是一个长的哈希值。我们还配置了插件在生命周期的验证阶段运行。

我们在生成的工件名称中使用了生成的构建号,通过附加它以及版本号。

现在,每次进行新的提交并且构建完成后,都会生成一个具有唯一名称的工件。根据需求,每个这样的工件都可以存档或追溯到相应的源。

发布 Maven 项目

任何项目的最终目标都是发布。在开发完成并修复了错误之后,就是发布项目的时候了。不同的项目以不同的方式发布。Web 项目通过部署到 Web 服务器来发布。其他项目可能被打包成可执行的 JAR 文件。还有一些可能被打包成可执行文件或安装程序。如果项目是一个库或被其他项目使用的依赖项,那么它需要以适当的方式提供。

如我们之前所见,我们在开发期间使用SNAPSHOT版本。当项目需要发布时,现在需要将这个版本替换为一个具体的版本。

Maven 最先进的功能之一是支持项目发布。让我们来探索这一点。

如何操作...

  1. 打开您想要发布的项目(project-with-release)。

  2. 验证 SCM 详细信息是否存在于 pom 文件中:

    <scm>
          <developerConnection>scm:git:https://bitbucket.org/maruhgar/apache-maven-cookbook</developerConnection>
           <url>https://bitbucket.org/maruhgar/apache-maven-cookbook</url>
        <tag>HEAD</tag>
      </scm>
    
  3. 添加插件定义以指定插件的最新版本:

       <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-release-plugin</artifactId>
            <version>2.5.1</version>
          </plugin>
        </plugins>
    
  4. 运行以下 Maven 命令:

    mvn release:prepare –DpushChanges=false
    
    

    默认情况下,插件所做的更改会被推送到仓库。如果您不希望这样做,可以将pushChanges配置选项设置为false

  5. 在提示时选择默认值。如何操作...

    您可以选择发布版本、SCM 标签和新开发版本的默认值,或者提供您的值。

  6. 观察输出:如何操作...

    Maven 运行了多个命令来修改 pom 文件。然后,它将这些更改检查到仓库中。

  7. 现在运行以下命令:

    mvn release:perform –Dgoals=package –DlocalCheckout=true
    
    

    默认情况下,Maven Release 插件的perform目标会运行deploy目标,将项目部署到指定的仓库。如果您没有远程仓库可以部署,或者想在发布过程中运行不同的目标,您可以使用goals配置来指定它。在前面的例子中,我们将其设置为运行package目标。

    此外,为了进行发布,Maven 会从仓库检出prepare目标创建的标签。如果您想让 Maven 检出本地副本,可以通过将localCheckout配置设置为true来实现。

  8. 观察输出:如何操作...

  9. 确保发布二进制文件在target/checkout/project-with-release/target文件夹中创建:如何操作...

它是如何工作的...

制作发布有两个步骤——准备和执行。

当运行 Maven Release 插件的prepare目标时,它执行以下操作:

  • 检查没有未提交的更改

  • 检查项目没有任何SNAPSHOT依赖项

  • 更改SNAPSHOT项目的版本;您将被提示确认或覆盖默认设置

  • scm元素中添加一个tag元素并计算其值(默认为HEAD

  • 运行verify目标以确保更改不会破坏任何内容

  • 将修改后的 pom 提交到 SCM

  • 在 SCM 中用版本名称标记代码(您将被提示确认或覆盖默认设置):如何工作...

  • 将 pom 中的版本提升到新的SNAPSHOT值(从1.0-SNAPSHOT变为1.1-SNAPSHOT);您将被提示确认或覆盖此设置

  • 将修改后的 pom 提交到 SCM

如您所见,一旦目标达成,您将有一个带有发布版本标签的更新后的 SCM,以及带有下一个SNAPSHOT版本的HEAD。还会创建一个release.properties文件。它包含执行perform目标所需的信息。

如何工作...

第二个平台执行如下:

  • perform目标使用release.properties中的信息从之前创建的 SCM 标签检出

  • 然后在检出的项目上运行指定的目标(默认为deploy

  • 这将生成发布二进制文件

一旦构建成功,Release 插件创建的release.properties和其他备份文件将被删除。

posted @ 2025-09-11 09:45  绝不原创的飞龙  阅读(3)  评论(0)    收藏  举报