Maven-简介-全-

Maven 简介(全)

原文:Introducing Maven

协议:CC BY-NC-SA 4.0

一、Maven 入门

像其他工匠一样,软件开发人员依靠他们的工具来构建应用程序。开发人员的集成开发环境(ide)、错误跟踪工具、构建工具、框架、容器和调试工具(如内存分析器)在高质量软件的日常开发和维护中起着至关重要的作用。这本书将讨论和探索 Maven 的特性,我们知道它将成为你的软件开发武库中的一个重要工具。

Apache Maven 是一个开源的、基于标准的项目管理框架,它简化了项目的构建、测试、报告和打包。Maven 最初源于 2000 年初的 Apache Jakarta Alexandria 项目。它随后被用于阿帕奇涡轮机项目。与当时的许多其他 Apache 项目一样,Turbine 项目有几个子项目,每个子项目都有自己的基于 Ant 的构建系统。当时,人们强烈希望开发一种标准的方法来构建项目,并在项目间轻松共享生成的工件。这种欲望催生了美文。Maven 版本发布于 2004 年,随后是 2005 年的 2.0 版本和 2010 年的 3.0 版本。在写这本书的时候,3.6.1 是 Maven 的当前版本。

Maven 已经成为全球企业中使用最广泛的开源软件程序之一。让我们来看看 Maven 如此受欢迎的一些原因。

标准化目录结构

通常,当我们开始一个新项目的工作时,会花费大量的时间来决定项目布局和存储代码和配置文件所需的文件夹结构。这些决策在不同的项目和团队中会有很大的不同,这使得新开发人员很难理解和采用其他团队的项目。这也使得现有的开发者很难在不同的项目之间跳跃,找到他们想要的东西。

Maven 通过标准化项目的文件夹结构和组织来解决上述问题。Maven 就项目的不同部分,比如源代码、测试代码和配置文件,应该放在哪里提供了建议。例如,Maven 建议所有的 Java 源代码都应该放在src\main\java folder中。这使得理解和导航任何 Maven 项目变得更加容易。

此外,这些约定使得切换到新的 IDE 并开始使用它变得很容易。从历史上看,ide 随着项目结构和文件夹名称的不同而不同。Eclipse 中的动态 web 项目可能使用 WebContent 文件夹来存储 web 资产,而 IntelliJ IDEA 可能使用 web 文件夹来实现相同的目的。使用 Maven,您的项目遵循一致的结构,并且不依赖于 IDE。

声明性依赖管理

大多数 Java 项目依赖于其他项目和开源框架才能正常运行。手动下载这些依赖项并在项目中使用它们时跟踪它们的版本可能会很麻烦。

Maven 提供了一种便捷的方式,在一个单独的外部pom.xml文件中声明这些项目依赖关系。然后,它会自动下载这些依赖项,并允许您在项目中使用它们。这极大地简化了项目依赖性管理。需要注意的是,在pom.xml文件中,你指定的是什么而不是如何pom.xml文件也可以作为一个文档工具,传达你的项目依赖和它们的版本。

外挂程式

Maven 遵循一个基于插件 - 的架构,使得增加和定制其功能变得容易。这些插件封装了可重用的构建和任务逻辑。今天,有数百个可用的 Maven 插件可以用来执行从代码编译到打包到项目文档生成的任务。

Maven 还使创建您自己的插件变得容易,从而使您能够集成特定于您的组织的任务和工作流。

统一构建抽象

Maven 为构建项目提供了统一的接口。您可以通过使用少量命令来构建 Maven 项目。一旦您熟悉了 Maven 的构建过程,您就可以很容易地弄清楚如何构建其他 Maven 项目。这将开发人员从学习构建特性中解放出来,这样他们就可以更加专注于开发。

工具支持

Maven 提供了一个强大的命令行界面来执行不同的操作。今天所有主流的 ide 都为 Maven 提供了优秀的工具支持。此外,Maven 完全集成了当今的持续集成产品,如 Jenkins 和 Bamboo。

原型

正如我们已经提到的,Maven 为它的项目提供了标准的目录布局。当创建新的 Maven 项目时,您需要手动构建每个目录,这很容易变得繁琐。这就是 Maven 原型来拯救的地方。Maven 原型是预定义的项目模板,可以用来生成新的项目。使用原型创建的项目将包含让您继续工作所需的所有文件夹和文件。

原型也是一个有价值的工具,用于捆绑您将在每个项目中需要的最佳实践和公共资产。考虑一个大量从事基于 Spring 框架的 web 应用程序的团队。所有基于 Spring 的 web 项目共享共同的依赖项,并且需要一组配置文件。很有可能所有这些 web 项目都有相似的Log4j/Logback配置文件、CSS/Images和百里香页面布局。Maven 让这个团队将这些公共资产捆绑成一个原型。当使用这个原型创建新项目时,它们将自动包含公共资产。不再需要复制和粘贴代码或拖放文件。

开放源码

Maven 是开源的,下载和使用都是免费的。它附带了丰富的在线文档和活跃社区的支持。

约定胜于配置

约定优于配置 (CoC)或编码 按约定是 Maven 的关键租户之一。由 Ruby on Rails 社区推广的 CoC 强调合理的缺省值,从而减少了决策的数量。这不仅节省了时间,还简化了最终产品,因为所需的配置数量大幅减少。

作为遵守 CoC 的一部分,Maven 为其项目提供了几个合理的缺省值。它设计了一个标准的目录结构,并为生成的工件提供了默认值。想象一下看一个名为log4j-core-2.11.2.jar的 Maven 工件。一眼就能看出您正在查看一个log4j-core JAR 文件,版本 2.11.2。

Maven 的 CoC 的一个缺点是最终用户在使用它时会感到僵硬。为了解决这个问题,您可以定制 Maven 的大多数默认设置。例如,可以更改 Java 源代码在项目中的位置。然而,根据经验,这种对默认值的更改应该最小化。

Maven 替代方案

虽然这本书的重点是 Maven,但让我们看看它的几个替代方案:Ant + Ivy 和 Gradle。

安特+艾维

Apache Ant ( http://ant.apache.org )是一个流行的用于脚本构建的开源工具。Ant 是基于 Java 的,它使用可扩展标记语言(XML)进行配置。Ant 的默认配置文件是build.xml文件。

使用 Ant 通常需要定义任务和目标。顾名思义,一个蚂蚁 任务是一个需要完成的工作单元。典型的任务包括创建目录、运行测试、编译源代码、构建 web 应用程序归档(WAR)文件等等。一个目标仅仅是一组任务。一个目标可能依赖于其他目标。这种依赖性让我们可以对目标执行进行排序。清单 1-1 展示了一个简单的build.xml文件,其中有一个名为compile的目标。compile目标有两个echo任务和一个javac任务。

<project name="Sample Build File" default="compile" basedir=".">

   <target name="compile" description="Compile Source Code">
      <echo message="Starting Code Compilation"/>
      <javac srcdir="src" destdir="dist"/>
      <echo message="Completed Code Compilation"/>
   </target>

</project>

Listing 1-1Sample Ant build.xml File

Ant 不会对您的项目强加任何约定或限制,而且众所周知它非常灵活。这种灵活性有时会导致复杂、难以理解和难以维护的build.xml文件。

Apache Ivy ( http://ant.apache.org/ivy/ )提供了自动化的依赖管理,让 Ant 使用起来更加愉悦。使用 Ivy,您可以在名为ivy.xml的 XML 文件中声明依赖关系,如清单 1-2 所示。集成 Ivy 和 Ant 需要在build.xml文件中声明新的目标来检索和解析依赖关系。

<ivy-module version="2.0">
  <info organisation="com.apress" module="gswm-ivy" />

  <dependencies>
      <dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.11.2" />
  </dependencies>
</ivy-module>

Listing 1-2Sample Ivy Listing

格拉德尔

Gradle ( http://gradle.org/ )是一个开源的构建、项目自动化工具,可用于 Java 和非 Java 项目。与 Ant 和 Maven 使用 XML 进行配置不同,Gradle 使用基于 Groovy 的领域特定语言 (DSL)。

Gradle 提供了 Ant 的灵活性,并且使用了相同的任务概念。清单 1-3 显示了一个默认的build.gradle文件。

plugins {
     id 'java'
}

version = '1.0.0'

repositories {
   mavenCentral()
}

dependencies {
    testCompileOnly group: 'junit', name: 'junit', version: '4.10'
}

Listing 1-3Default build.gradle File

Gradle 的 DSL 和它对 CoC 的坚持导致了紧凑的构建文件。清单 1-3 中的第一行包含一个供build使用的 Java 插件。Gradle 中的插件为项目提供了预配置的任务和依赖关系。例如,Java 插件提供了构建源文件、运行单元测试和安装工件的任务。文件default.build中的依赖部分指示 Gradle 在编译测试源文件时使用JUnit依赖。Gradle 的灵活性和性能使其越来越受欢迎。然而,Gradle 和 Groovy DSL 的学习曲线可能会很陡。与 Maven 相比,对 Gradle 的 IDE 和插件支持也不太成熟。

尽管来自其他工具的竞争越来越激烈,Maven 继续主导构建工具领域。这在图 1-1 中显而易见,图中显示了 synk . io(https://snyk.io/blog/jvm-ecosystem-report-2018-tools/)2018 年关于 Java 开发者使用的构建工具的调查结果。

img/332298_2_En_1_Fig1_HTML.png

图 1-1

构建工具使用的调查结果

Maven 项目的Polyglot(https://github.com/takari/polyglot-maven)允许您用除 XML 之外的方言创建 Maven 的 POM 文件。支持的语言包括 Groovy、Ruby、Scala、YAML 和 Java。

Maven 组件

Maven 依靠几个组件来完成它的工作。虽然您可能不会直接与这些组件进行交互,但是对这些组件的概述有助于理解 Maven 的内部工作方式,并使您能够更好地排除 Maven 错误。

胃十二指肠切除术

Maven 与几个源代码控制/代码管理(SCM)系统进行交互,以执行诸如签出代码或创建分支或标签之类的操作。Maven SCM ( http://maven.apache.org/scm/ )项目提供了一个通用的 API 来执行这样的操作。第八章中讨论的 Maven release 插件严重依赖于 Maven SCM 组件。Maven SCM 目前支持几个流行的代码管理系统,如 Git、Subversion 和 Perforce。

Maven 旅行车

如前所述,Maven 自动从不同的位置(如 FTPs、文件系统和网站)下载项目依赖项,如 JAR 文件。Maven Wagon ( https://maven.apache.org/wagon/ )项目提供了一个传输抽象,使 Maven 能够轻松地与不同的传输协议交互并检索依赖关系。Maven Wagon 支持一些流行的协议,例如

  1. 文件:允许使用文件系统协议检索依赖关系。

  2. HTTP :允许使用 HTTP/HTTPS 协议检索依赖关系。提供了两种实现变体——一种使用 Apache HttpClient,另一种使用标准 Java 库。

  3. FTP :允许使用文件传输协议检索依赖关系。

梅文·多夏

Maven Doxia ( https://maven.apache.org/doxia/ )是一个内容生成框架,可以用来生成静态/动态内容,比如 PDF 文件和网页。Doxia 支持几种流行的标记语言,如 Markdown、Apt、XHTML 和 Confluence。Maven 非常依赖 Doxia 来生成项目文档和报告(在第七章中有更多相关内容)。

摘要

Apache Maven 极大地简化了构建过程并自动化了项目管理任务。本章简要介绍了 Maven,并描述了采用它的主要原因。我们还看了 Maven 的亲密同行:Ant + Ivy 和 Gradle。

在下一章中,您将了解启动和运行 Maven 所需的设置。

二、设置 Maven

Maven 安装是一个简单直接的过程。本章将解释如何使用 Windows 10 和 Mac 操作系统安装和设置 Maven。对于其他操作系统,您可以遵循类似的过程。

注意

Maven 是一个基于 Java 的应用程序,需要 Java 开发工具包(JDK)才能正常工作。Maven 版需要 JDK 1.7 或更高版本。在继续安装 Maven 之前,请确保您已经安装了 Java。如果没有,从 www.oracle.com/technetwork/java/javase/downloads/index.html 安装 JDK(不仅仅是 Java 运行时环境[JRE])。确保设置了JAVA_HOME环境变量并指向 JDK 安装。在本书中,我们将使用 JDK 8。

您将通过从 Apache Maven 网站( http://maven.apache.org/download.html )下载最新版本的 Maven 来开始安装过程。在撰写本文时,最新版本是 3.6.1。下载如图 2-1 所示的 Maven 3.6.1 二进制.zip文件。

img/332298_2_En_2_Fig1_HTML.jpg

图 2-1

Maven 档案下载

下载完成后,将发行版解压缩到您计算机上的本地目录。它将创建一个名为apache-maven-3.6.1-bin的文件夹,该文件夹的内容如图 2-2 所示。

img/332298_2_En_2_Fig2_HTML.jpg

图 2-2

Maven 安装目录内容

bin 文件夹包含特定于平台的 Maven 可执行文件–用于 Windows 的 mvn.cmd 文件和用于 Mac 和 Unix/Linux 平台的 mvn.sh 文件,您可以使用它们来启动 Maven。这些可执行文件的调试版本——mvndebug . cmd 和 mvndebug . sh——包括调试参数,允许您将 IDE 附加到正在运行的 Maven 进程,以便进行远程调试。

该引导文件夹包含“plexus-classworlds-2.5.2.jar”文件。Maven 使用丛类世界框架( https://codehaus-plexus.github.io/plexus-classworlds/ )来构建它的类加载器图。

conf 文件夹包含配置文件,您可以使用这些文件来改变 Maven 的默认行为。这个文件夹中的一个重要文件是 settings.xml 文件,我们将在本章的后面介绍它。另一个文件是 simplelogger.properties 文件,它允许您控制 Maven 的日志记录。例如,通过将 defaultLogLevel 属性设置为 debug,可以将日志级别更改为 debug。同样,您可以更改 logFile 属性,将“System.out”中的日志输出写入一个文件。

最后,lib 文件夹包含 Maven 及其插件正常运行所必需的库。

在 Windows 上安装

将 apache-maven-3.6.0-bin 的内容移动到一个新目录 c:\tools\maven。下一步是将 Maven 可执行文件添加到 PATH 环境变量中,以便您可以从命令行运行 Maven 命令。在 Windows 搜索框中,搜索“环境变量”并选择“编辑系统环境变量”。在出现的窗口中,单击环境变量按钮,选择路径变量,然后单击编辑。单击 New 并输入值“C:/tools/maven/bin ”,然后单击 OK。

在 Mac 上安装

将 apache-maven-3.6.0-bin 文件夹的内容移动到$HOME/tools/maven 中,其中$HOME 是您在 Mac 上的主目录。编辑。bash_profile 文件,方法是运行命令nano ~/.bash_profile。通过将以下代码行添加到,将 Maven 可执行文件添加到 PATH 变量。bash_profile:

export PATH=$HOME/tools/maven/bin:$PATH

这就完成了 Maven 的安装。如果您有任何打开的命令行窗口/终端,请将其关闭并重新打开一个新的命令行窗口。当添加或修改环境变量时,新值不会自动传播到打开的命令行窗口。

Maven_Opts 环境变量

当使用 Maven 时,尤其是在一个复杂的项目中,您可能会遇到内存不足的错误。例如,当您运行大量 JUnit 测试或生成大量报告时,这种情况可能会发生。要解决这个错误,请增加 Maven 使用的 Java 虚拟机(JVM)的堆大小。这是通过创建一个名为MAVEN_OPTS的新环境变量来全局完成的。首先,我们建议使用值-Xmx512m

测试装置

现在已经安装了 Maven,是时候测试和验证安装了。打开命令提示符并运行以下命令:

mvn –v

在 Windows 计算机上,此命令应输出类似于以下内容的信息:

C:\> mvn –v
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T13:00:29-06:00)
Maven home: C:\tools\maven\bin\..
Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: C:\Java\jdk1.8.0_144\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

–v命令行选项告知 Maven 的安装路径以及它使用的 Java 版本。运行扩展命令mvn --version也会得到相同的结果。

获得帮助

您可以通过使用-h--help选项获得 Maven 的命令行选项列表。运行以下命令将产生类似于图 2-3 所示的输出。

img/332298_2_En_2_Fig3_HTML.jpg

图 2-3

运行 Maven Help 命令的结果

mvn -h

附加设置

到目前为止,我们提供的安装步骤足以让您开始使用 Maven。但是,对于大多数企业用途,您需要提供额外的配置信息。这个用户特定的配置在一个settings.xml文件中提供。Maven 在两个位置查找 settings.xml 文件——Maven 安装的 conf 文件夹和用户主目录的. m2 文件夹。conf 文件夹下的 settings.xml 文件称为全局设置,. m2 文件夹下的文件称为用户设置。如果两个文件都存在,Maven 将合并两个文件的内容,用户设置优先。

注意

.m2文件夹对 Maven 的顺利运行很重要。其中,这个文件夹包含一个settings.xml文件和一个存储库文件夹。存储库文件夹包含 Maven 需要的插件JAR文件和元数据。它还包含 Maven 从互联网上下载的依赖于项目的 JAR 文件。我们将在第三章中仔细查看这个文件夹。

默认情况下,.m2文件夹位于您的主目录中。在 Windows 中,这个目录通常是c:\Users\<<your_user_name>>。在 Mac 上,这个目录通常是/Users/<<your_user_name>>/. m2/repository。您可以运行命令 mvn help:evaluate-d expression = settings . local repository 来标识本地存储库位置。</your_user_name>

当您运行 Maven 命令时,Maven 会自动创建.m2文件夹。但是,如果您在计算机上没有看到此文件夹,请继续创建一个。

开箱即用,.m2文件夹不包含settings.xml文件。在本地计算机上的.m2文件夹中,创建一个settings.xml文件,并复制骨架settings.xml文件的内容,如清单 2-1 所示。我们将在接下来的章节中讨论其中的一些元素。表 2-1 中提供了一些元素的简要说明。

表 2-1

细节 settings.xml 元素

|

元素名称

|

描述

|
| --- | --- |
| localRepository | Maven 将插件和依赖项的副本存储在本地的c:\Users\<<your_user_name>>\.m2\repository文件夹中。localRepository 元素可用于更改本地存储库的路径。例如,<localRepository>c:\mavenrepo</localRepository>会将存储库的位置更改为mavenrepo文件夹。 |
| interactiveMode | 顾名思义,当这个值设置为true时,Maven 与用户交互进行输入。如果值为 false,Maven 将尝试使用合理的默认值。默认值为 true。 |
| offline | 当设置为true时,该配置指示 Maven 不要连接到网络并在离线模式下运行。当 offline mode 设置为 true 时,Maven 不会尝试下载新的依赖项或对依赖项的更新。默认为false。 |
| servers | Maven 可以与各种服务器进行交互,比如 Git 服务器、构建服务器和远程存储库服务器。该元素允许您指定连接到这些服务器所需的安全凭证,如用户名和密码。 |
| mirrors | 顾名思义,镜像允许您指定从远程存储库下载依赖项的备用位置。例如,您的组织可能在其内部网络上镜像了一个公共存储库。mirror 元素允许您强制 Maven 使用内部镜像存储库,而不是公共存储库。 |
| proxies | 代理包含连接到互联网所需的 HTTP 代理信息。 |

<settings 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          http://maven.apache.org/xsd/settings-1.0.0.xsd">
      <localRepository/>
      <interactiveMode/>
      <offline/>
      <pluginGroups/>
      <servers/>
      <mirrors/>
      <proxies/>
      <profiles/>
      <activeProfiles/>
</settings>

Listing 2-1Skeleton Settings.xml Contents

设置代理

正如我们将在第三章中详细讨论的,Maven 需要一个互联网连接来下载插件和依赖项。一些公司使用 HTTP 代理来限制对互联网的访问。在这些场景中,运行 Maven 将导致无法下载工件的错误。要解决这个问题,请编辑settings.xml文件并添加特定于您公司的代理信息。清单 2-2 中显示了一个示例配置。

<settings 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <proxies>
    <proxy>
      <id>companyProxy</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.company.com</host>
      <port>8080</port>
      <username>proxyusername</username>
      <password>proxypassword</password>
      <nonProxyHosts />
    </proxy>
  </proxies>
 </settings>

Listing 2-2Settings.xml with Proxy Content

保护密码

第 2-2 节中连接到代理服务器的密码以明文形式存储在 settings.xml 文件中。如果您不小心共享了 settings.xml 文件,您的密码就会泄露。为了解决这个问题,Maven 提供了一种机制来加密存储在 settings.xml 文件中的密码。

我们通过使用以下代码创建主密码来开始加密过程:

   mvn -emp mymasterpassword
{LCWw0+NAqw0HuYH9HNz+1D7aElXM242PtuyoDXDAuelxjwZC8MyXaACkHSy7tZwU}

Maven 要求将新生成的主密码保存在. m2 文件夹下的 settings-security.xml 文件中。在. m2 文件夹下创建一个新的 settings-security.xml 文件,并将以下内容复制到该文件中。

<settingsSecurity>
<master>{LCWw0+NAqw0HuYH9HNz+1D7aElXM242PtuyoDXDAuelxjwZC8MyXaACkHSy7tZwU}</master>
</settingsSecurity>

运行以下命令来加密“proxypassword”密码。命令完成后,复制输出并用它替换 settings.xml 文件中的明文密码:

mvn -ep proxypassword
{i4RnaIHgxqgHyKYySxor+cvshmHweTAvNjuORNYyu5w=}

尽管前面的过程对密码进行了加密,并且避免了以明文形式保存密码的需要,但是一定要记住,能够访问 settings-security.xml 文件的任何人都可以轻松地解码主密码,并随后解密 settings.xml 文件中的密码。解决这个问题的一种机制是将 settings-security.xml 文件存储在外部设备中,如 USB 驱动器。

IDE 支持

在本书中,我们将使用命令行来创建和构建示例应用程序。如果您对使用 IDE 感兴趣,好消息是所有现代 IDE 都集成了 Maven,不需要任何进一步的配置。

摘要

本章引导你在本地计算机上安装 Maven。您了解了 Maven 下载其运行所需的插件和工件。这些工件存储在。m2\repository文件夹。.m2文件夹还包含了settings.xml文件,可以用来配置 Maven 的行为。

在下一章,我们将更深入地研究 Maven 的依赖管理。

三、Maven 依赖管理

企业级项目通常依赖于各种开源库。考虑您想要使用Log4J进行应用程序日志记录的场景。为了完成这一点,您可以转到Log4J下载页面,下载JAR文件,并把它放在项目的lib文件夹中,或者把它添加到项目的类路径中。这种方法有几个问题:

  1. 您下载的JAR文件可能依赖于其他一些库。您现在必须找到所有这些依赖项(以及它们的依赖项)并将它们添加到您的项目中。

  2. 到了升级JAR文件的时候,你需要重新开始这个过程。

  3. 您需要将JAR文件与您的源代码一起添加到源代码控制中,这样您的项目就可以在您自己的计算机之外的计算机上构建。这增加了项目规模、检验和构建时间。

  4. 在组织内的团队间共享文件变得很困难。

为了解决这些问题,Maven 提供了声明性依赖管理。使用这种方法,您可以在一个名为pom.xml的外部文件中声明项目的依赖项。Maven 将自动下载这些依赖项,并出于构建、测试或打包的目的将它们交给您的项目。

图 3-1 显示了 Maven 依赖性管理的高级视图。当您第一次运行您的 Maven 项目时,Maven 连接到网络并从远程存储库中下载工件和相关的元数据。默认的远程仓库被称为 Maven Central ,它位于repo.maven.apache.orguk.maven.org。Maven 将这些下载的工件的副本放在其本地存储库中。在随后的运行中,Maven 将在其本地存储库中寻找一个工件;如果没有找到工件,Maven 将尝试从远程存储库下载它。

img/332298_2_En_3_Fig1_HTML.jpg

图 3-1

Maven 依赖管理

尽管图 3-1 中所示的架构在大多数情况下都能工作,但它在企业环境中会带来一些问题。第一个问题是在团队之间共享公司相关的工件是不可能的。出于安全和知识产权的考虑,您不希望在 Maven Central 上发布您企业的工件。另一个问题涉及法律和许可问题。您的公司可能希望团队只使用官方批准的开源软件,而这种架构不适合该模型。最后一个问题是带宽和下载速度。在 Maven Central 负载较重的时候,Maven 工件的下载速度会降低,这可能会对您的构建产生负面影响。因此,大多数企业采用如图 3-2 所示的架构。

img/332298_2_En_3_Fig2_HTML.jpg

图 3-2

企业 Maven 存储库架构

内部存储库管理器充当远程存储库的代理。这允许您缓存来自远程存储库的工件,从而加快工件下载并提高构建性能。因为您拥有对内部存储库的完全控制权,所以您可以管理您公司中允许的工件类型。此外,您还可以将您组织的工件推到 repository manager 上,从而实现协作。如表 3-1 所示,有几个开源存储库管理器。

表 3-1

开源存储库管理器

|

存储库管理器

|

统一资源定位器

|
| --- | --- |
| Nexus 存储库操作系统 | www.sonatype.com/nexus-repository-oss |
| Apache 归档 | http://archiva.apache.org/ |
| Artifactory 开源 | https://jfrog.com/open-source/#artifactory |

使用新的存储库

为了使用新的存储库,您需要修改您的settings.xml文件。清单 3-1 显示了添加到settings.xml文件中的 Spring 和 JBoss 存储库。同样,您可以添加您公司的存储库管理员。

注意

关于存储库的信息可以在settings.xmlpom.xml文件中提供。每种方法都有利弊。将存储库信息放在pom.xml文件中可以使您的构建具有可移植性。它使开发人员能够下载项目并简单地构建它们,而无需进一步修改他们的本地settings.xml文件。这种方法的问题是,当工件被发布时,相应的pom.xml文件将存储库信息硬编码在其中。如果存储库 URL 发生了变化,这些工件的消费者将会由于存储库路径的中断而遇到错误。将存储库信息放在settings.xml文件中解决了这个问题,并且由于它提供的灵活性,在企业设置中通常推荐使用settings.xml方法。

<?xml version="1.0" encoding="UTF-8" ?>
<settings  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  .......

      <profiles>
          <profile>
            <id>your_company</id>
            <repositories>
                   <repository>
                     <id>spring_repo</id>
                     <url>http://repo.spring.io/release/</url>
                   </repository>
                   <repository>
                     <id>jboss_repo</id>
                     <url>https://repository.jboss.org/</url>
                   </repository>
            </repositories>
          </profile>
      </profiles>
      <activeProfiles>
      <activeProfile>your_company</activeProfile>
      </activeProfiles>

  .......

</settings>

Listing 3-1Adding Repositories in settings.xml

依赖性识别

Maven 依赖项通常是 JAR、WAR、enterprise archive (EAR)和 ZIP 等归档文件。每个 Maven 依赖项都使用以下组、工件和版本(GAV)坐标进行唯一标识:

  • groupId:负责该项目的组织或团体的标识。例子包括org.hibernatelog4jorg.springframework和 com.companyname

  • artifactId:项目正在生成的工件的标识符。这在使用相同groupId的项目中必须是唯一的。例子包括 hibernate-tools、log4j、spring-core 等等。

  • version:表示项目的版本号。示例包括 1.0.0、2 . 3 . 1-快照和 5.4.2 .最终版本

  • type:表示对生成的工件进行打包。示例包括 JAR、WAR 和 EAR。

仍在开发中的工件在它们的版本中用快照标记。一个示例版本是 1.0-快照。这告诉 Maven 每天从远程存储库中寻找工件的更新版本。

使用 Dependencies 标记在 pom.xml 文件中声明依赖关系,如下所示:

<dependencies>
      <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-tools</artifactId>
             <version>5.4.2.Final</version>
      </dependency>
</dependencies>

传递依赖性

在项目的pom.xml文件中声明的依赖项通常有自己的依赖项。这样的依赖被称为传递依赖。以 Hibernate 核心为例。为了让它正常工作,它需要 JBoss 日志、dom4j、javaassist 等等。在您的pom.xml文件中声明的 Hibernate 核心被认为是一个直接依赖项,而像 dom4j 和 javaassist 这样的依赖项被认为是项目的可传递依赖项。Maven 的一个主要优点是,它自动处理可传递的依赖项,并将它们包含在您的项目中。

图 3-3 提供了一个传递依赖的例子。请注意,可传递依赖项可以有自己的依赖项。正如您所想象的,这可能会很快变得复杂,尤其是当多个直接依赖项提取同一个 JAR 文件的不同版本时。

Maven 使用一种称为依赖中介的技术来解决版本冲突。简而言之,依赖中介允许 Maven 从依赖树中提取与项目最接近的依赖。在图 3-3 中,有两个版本的依赖 B: 0.0.8 和 1.0.0。在这个场景中,依赖项 B 的版本 0.0.8 包含在项目中,因为它是一个直接依赖项,并且是最接近树的。现在看一下依赖 F 的三个版本:0.1.3、1.0.0 和 2.2.0。所有三个依赖项都在同一深度。在这个场景中,Maven 将使用第一个找到的依赖项,这将是 0.1.3,而不是最新的 2.2.0 版本。如果您希望 Maven 使用工件 F 的最新 2.2.0 版本,您需要显式地将该版本依赖项添加到 pom.xml 文件中。

img/332298_2_En_3_Fig3_HTML.jpg

图 3-3

传递依赖性

虽然非常有用,但是可传递的依赖关系可能会导致问题和不可预知的副作用,因为您可能最终会包含不需要的 JAR 文件或旧版本的 JAR 文件。Maven 提供了一个方便的依赖插件,允许您可视化项目依赖树。清单 3-2 显示了在一个样本项目上运行依赖目标的输出。可以看到该项目依赖于 4.11 版本的 JUnit JAR 文件。JUnit JAR 本身依赖于 1.3 版本的 hamcrest JAR 文件。

[sudha]$mvn dependency:tree
[INFO] Scanning for projects...
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ gswm
[INFO] com.apress.gswmbook:gswm:jar:1.0.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.11:test
[INFO]    \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] -----------------------------------------------
[INFO] BUILD SUCCESS

Listing 3-2Maven Dependency Tree Plug-in

有时候,您不希望在最终的归档中包含某些可传递的依赖 jar。例如,在 Tomcat 或 WebLogic 等容器中部署应用程序时,您可能希望排除某些 JAR 文件,如 servlet-api 或 javaee-api,因为它们会与容器加载的版本冲突。Maven 提供了一个“excludes”标签来排除可传递的依赖关系。清单 3-3 显示了从 JUnit 依赖项中排除 hamcrest 库的代码。如您所见,exclusion元素接受您想要排除的依赖项的groupIdartifactId坐标。

<dependencies>
      <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>${junit.version}</version>
             <scope>test</scope>
             <exclusions>
                   <exclusion>
                         <groupId>org.hamcrest</groupId>
                         <artifactId>hamcrest</artifactId>
                   </exclusion>
             </exclusions>
      </dependency>
</dependencies>

Listing 3-3JUnit Dependency with Exclusion

依赖范围

考虑一个使用 JUnit 进行单元测试的 Java 项目。您包含在项目中的 JUnit JAR文件只在测试期间需要。您真的不需要将 JUnit JAR捆绑到您的最终产品档案中。类似地,考虑 MySQL 数据库驱动程序,mysql-connector-java.jar文件。当您在诸如 Tomcat 之类的容器中运行应用程序时,而不是在代码编译或测试期间,您需要 JAR 文件。Maven 使用了作用域的概念,它允许您指定何时何地需要特定的依赖项。

Maven 提供了以下六个范围:

  • compile:在项目构建、测试和运行的所有阶段,类路径中都有与compile范围的依赖关系。这是默认范围。

  • provided:在构建和测试阶段,与provided范围的依赖关系在类路径中是可用的。它们不会被捆绑在生成的工件中。使用这个范围的依赖关系的例子包括 Servlet api、JSP api 等等。

  • runtime:在构建阶段,与runtime范围的依赖关系在类路径中不可用。相反,它们被捆绑在生成的工件中,并在运行时可用。

  • test:与test范围的依赖关系在测试阶段是可用的。JUnit 和 TestNG 是依赖测试范围的好例子。

  • system:与system范围的依赖关系类似于与provided范围的依赖关系,除了这些依赖关系不是从存储库中检索的。相反,指定了文件系统的硬编码路径,从该路径使用依赖关系。

  • import:import范围仅适用于.pom文件依赖。它允许您包含来自远程.pom文件的依赖管理信息。import范围仅在 Maven 2.0.9 或更高版本中可用。

手动依赖安装

理想情况下,您将从公共存储库或您的企业存储库管理器中提取项目中的依赖项。但是,有时您需要在本地存储库中有一个可用的档案,以便您可以继续开发。例如,您可能正在等待系统管理员将所需的JAR文件添加到您的企业存储库管理器中。

Maven 提供了一种使用安装插件将归档文件安装到本地存储库中的简便方法。清单 3-4 安装一个位于c:\apress\gswm-book\chapter3文件夹中的test.jar文件。

C:\apress\gswm-book\chapter3>mvn install:install-file -DgroupId=com.apress.gswmbook -DartifactId=test -Dversion=1.0.0 -Dfile=C:\apress\gswm-book\chapter3\test.jar -Dpackaging=jar -DgeneratePom=true
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< org.apache.maven:standalone-pom >---------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] -------------------------[ pom ]------------------------
[INFO]
[INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom ---
[INFO] Installing C:\apress\gswm-book\chapter3\test.jar to C:\Users\bavara\.m2\repository\com\apress\gswmbook\test\1.0.0\test-1.0.0.jar
[INFO] Installing C:\Users\bavara\AppData\Local\Temp\mvninstall5971068007426768105.pom to C:\Users\bavara\.m2\repository\com\apress\gswmbook\test\1.0.0\test-1.0.0.pom
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------
[INFO] Total time:  0.439 s
[INFO] Finished at: 2019-09-01T00:05:21-06:00
[INFO] --------------------------------------------------------

Listing 3-4Installing Dependency Manually

看到BUILD SUCCESS消息后,您可以通过访问本地 Maven 库来验证安装,如图 3-4 所示。

img/332298_2_En_3_Fig4_HTML.jpg

图 3-4

相关性已添加到存储库中

摘要

依赖性管理是 Maven 的核心。每个重要的 Java 项目都依赖于开源或外部工件,Maven 的依赖性管理自动化了检索这些工件并将其包含在构建过程的正确阶段的过程。您还了解了 Maven 使用 GAV 坐标来识别其工件。

在下一章,你将学习一个基本 Maven 项目的组织。

四、Maven 项目基础

Maven 为其所有项目提供了约定和标准的目录布局。正如在第一章中所讨论的,这种标准化提供了一个统一的构建接口,也使得开发者可以很容易地从一个项目跳到另一个项目。本章将解释 Maven 项目的基础知识和 pom.xml 文件。

基本项目组织

理解 Maven 项目结构的最好方法是看一个。图 4-1 展示了一个基于 Maven 的基本 Java 项目。

img/332298_2_En_4_Fig1_HTML.png

图 4-1

Maven Java 项目结构

现在让我们看看项目中的每个组件:

  • gswm是项目的根文件夹。通常,根文件夹的名称与生成的工件的名称相匹配。

  • src文件夹包含与项目相关的工件,比如源代码或属性文件,您通常希望在一个源代码控制管理 (SCM)系统中管理它们,比如 SVN 或 Git。

  • src/main/java文件夹包含 Java 源代码。

  • src/test/java文件夹包含 Java 单元测试代码。

  • target文件夹保存生成的工件,比如.class文件。生成的工件通常不存储在 SCM 中,所以不要将目标文件夹及其内容提交到 SCM 中。

  • LICENSE.txt文件包含与项目相关的许可信息。

  • README.txt文件包含关于项目的信息/说明。

  • NOTICE.txt文件包含本项目使用的第三方库所需的通知。

  • 每个 Maven 项目在项目的根目录下都有一个pom.xml文件。它保存项目和配置信息,比如依赖项和插件。

除了src/mainsrc/test目录,Maven 还推荐了其他几个目录来保存额外的文件和资源。表 4-1 列出了这些目录以及其中的内容。

表 4-1

Maven 目录

|

目录名

|

描述

|
| --- | --- |
| src/main/resources | 保存资源,比如 Spring 配置文件和 velocity 模板,它们需要在生成的工件中结束。 |
| src/main/config | 保存配置文件,例如 Tomcat 上下文文件、James 邮件服务器配置文件等等。这些文件不会出现在生成的工件中。 |
| src/main/scripts | 包含系统管理员和开发人员应用程序所需的任何脚本。 |
| src/test/resources | 保存测试所需的配置文件。 |
| src/main/webapp | 保存 web 资产,如.jsp文件、样式表和图像。 |
| src/it | 保存应用程序的集成测试。 |
| src/main/db | 保存数据库文件,如 SQL 脚本。 |
| src/site | 保存项目网站生成过程中所需的文件。 |

Maven 提供原型(如第六章所讨论的)来快速启动项目。然而,在本章中,您将手工组装一个基于 Maven 的 Java 项目。使用以下说明创建项目:

  1. 使用命令行,转到要创建项目的文件夹。在本书中,我们假设该目录为c:\apress\gswm-book\chapter4

  2. 运行命令mkdir gswm

  3. cd到新创建的目录中,并创建一个空的pom.xml文件。

  4. gswm下创建src目录,然后在src下创建main目录,最后在main下创建java目录。

起始项目结构应类似于图 4-2 所示。

img/332298_2_En_4_Fig2_HTML.jpg

图 4-2

开始项目结构

了解 pom.xml 文件

pom.xml文件是 Maven 项目中最重要的文件。正如我们在本书中讨论的那样,pom.xml文件保存了 Maven 所需的配置信息。清单 4-1 显示了带有基本项目信息的pom.xml文件。我们以project元素开始pom.xml文件。然后我们提供groupIdartifactIdversion坐标。packaging元素告诉 Maven 它需要为这个项目创建一个JAR档案。最后,我们使用developers元素来添加关于从事这个项目的开发人员的信息。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Getting Started with Maven</name>
  <url>http://apress.com</url>

  <developers>
   <developer>
       <id>balaji</id>
       <name>Balaji Varanasi</name>
       <email>balaji@inflinx.com</email>
       <properties>
          <active>true</active>
       </properties>
   </developer>
   <developer>
      <id>sudha</id>
      <name>Sudha Belida</name>
      <email>sudha@inflinx.com</email>
      <properties>
          <active>true</active>
      </properties>
   </developer>
 </developers>
</project>

Listing 4-1pom.xml File Configuration

我们将在这一章的后面以及整本书的其余部分看到pom.xml文件中的其他元素。

Maven 版本控制

建议 Maven 项目使用以下约定进行版本控制:

<major-version>.<minor-version>.<incremental-version>-qualifier

主要值、次要值和增量值都是数字,限定符可以有 RC、alpha、beta 和 SNAPSHOT 等值。遵循此约定的一些示例包括 1.0.0、2.4.5 快照、3 . 1 . 1 RC1 等。

项目版本中的快照限定符具有特殊的含义。这表明该项目正处于开发阶段。当项目使用快照依赖时,每次构建项目时,Maven 都会获取并使用最新的快照工件。

大多数存储库经理只接受一次发布版本。然而,当您在持续集成环境中开发应用程序时,您希望经常进行构建,并将您的最新构建推送到 repository manager。因此,在开发过程中给你的版本加上快照是最好的做法。

构建项目

在我们开始构建项目之前,让我们在src/main/java文件夹下添加 HelloWorld Java 类。清单 4-2 显示了HelloWorld类的代码。

public class HelloWorld {
      public void sayHello() {
            System.out.print("Hello World");
      }
}

Listing 4-2Code for HelloWorld Java Class

图 4-3 显示了添加类后的项目结构。

img/332298_2_En_4_Fig3_HTML.jpg

图 4-3

添加了 Java 类的项目结构

现在您已经准备好构建应用程序了,所以让我们从gswm运行mvn package。您应该会看到类似于清单 4-3 所示的输出。

C:\apress\gswm-book\chapter4\gswm>mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------------------------------
[INFO] Building Getting Started with Maven 1.0.0-SNAPSHOT
[INFO] --------------------------------------------------------
...................
[INFO] Compiling 1 source file to C:\apress\gswm-book\chapter4\gswm\target\classes
...................
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ gswm ---
[INFO] Building jar: C:\apress\gswm-book\chapter4\gswm\target\gswm-1.0.0-SNAPSHOT.jar
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS

Listing 4-3Output for Maven Package Command for Building the Application

注意

如果这是您第一次运行 Maven,它将下载运行它所需的插件和依赖项。因此,您的第一次构建可能比您预期的要长。

mvn命令后面的后缀是一个 Maven 阶段,它编译 Java 代码并将其打包到JAR文件中。打包后的JAR文件在gswm\target文件夹中结束,如图 4-4 所示。

img/332298_2_En_4_Fig4_HTML.jpg

图 4-4

打包的JAR位于目标文件夹下

测试项目

现在您已经完成了项目构建,让我们添加一个测试sayHello()方法的JUnit测试。让我们通过将JUnit依赖项添加到pom.xml文件来开始这个过程。您可以通过使用dependencies元素来实现这一点。清单 4-4 显示了带有JUnit依赖关系的更新后的pom.xml文件。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Getting Started with Maven</name>
  <url>http://apress.com</url>

  <developers>
   <developer>
      <id>balaji</id>
      <name>Balaji Varanasi</name>
      <email>balaji@inflinx.com</email>
       <properties>
          <active>true</active>
       </properties>
   </developer>
   <developer>
      <id>sudha</id>
      <name>Sudha Belida</name>
      <email>sudha@inflinx.com</email>
      <properties>
          <active>true</active>
      </properties>
   </developer>
 </developers>
   <dependencies>
       <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.12</version>
              <scope>test</scope>
       </dependency>
</dependencies>

</project>

Listing 4-4Updated POM with JUnit Dependency

注意,您已经使用了作用域test,表明JUnit .jar只在测试阶段需要。让我们通过在命令行中运行mvn dependency:tree来确保这个依赖项已经被成功添加。清单 4-5 显示了该操作的输出。

C:\apress\gswm-book\chapter4\gswm>mvn dependency:tree
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ gswm ---
[INFO] com.apress.gswmbook:gswm:jar:1.0.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.12:test
[INFO]    \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS

Listing 4-5Maven Tree Command Output

依赖关系插件中的树目标将项目的依赖关系显示为tree。请注意,JUnit依赖项引入了一个名为hamcrest的可传递依赖项,这是一个开源项目,可以很容易地编写匹配器对象。

既然在类路径中有了JUnit依赖项,那么让我们向项目中添加一个单元测试HelloWorldTest.java。在src下创建test/java文件夹,并在其下添加HelloWorldTest.java。更新后的项目结构如图 4-5 所示。

img/332298_2_En_4_Fig5_HTML.jpg

图 4-5

带有测试类的 Maven 结构

清单 4-6 中显示了HelloWorldTest的源代码。

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class HelloWorldTest {

      private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();

      @Before
      public void setUp() {
          System.setOut(new PrintStream(outStream));
      }

      @Test
      public void testSayHello() {
            HelloWorld hw = new HelloWorld();
            hw.sayHello();
            Assert.assertEquals("Hello World", outStream.toString());
      }

      @After
      public void cleanUp() {
          System.setOut(null);
      }

}

Listing 4-6Code for HelloWorldTest Java Class

现在您已经在这个项目中设置好了一切,所以您可以再次运行mvn包。运行之后,您将看到类似于清单 4-7 中所示的输出。

C:\apress\gswm-book\chapter4\gswm>mvn package
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ gswm ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ gswm ---
---------------------------------------------------------------
[INFO] Surefire report directory: C:\apress\gswm-book\chapter4\gswm\target\surefire-reports
---------------------------------------------------------------
 T E S T S
---------------------------------------------------------------
Running HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.038 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ gswm ---
[INFO] Building jar: C:\apress\gswmbook\chapter4\gswm\target\gswm-1.0.0-SNAPSHOT.jar
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS

Listing 4-7Output for Maven Command for Building the Project

注意清单 4-7 中的测试部分。它显示 Maven 已经运行了测试,并且测试已经成功完成。

图 4-6 显示更新后的目标文件夹。您可以看到现在有了一个test-classes文件夹,该文件夹中有相关的报告。

img/332298_2_En_4_Fig6_HTML.jpg

图 4-6

包含测试类的目标文件夹

pom.xml 中的属性

Maven 提供了可以在 pom.xml 文件中使用的属性,即占位符。Maven 属性在 pom.xml 文件中使用${ property _ name }符号引用。有两种类型的属性-隐式属性和用户定义的属性。

隐含属性

隐式属性是默认情况下可用于任何 Maven 项目的属性。例如,Maven 使用“项目”来公开它的项目对象模型属性前缀。要访问 pom.xml 文件中的 artifactId 值,可以使用${ project。artifactId}如下所示:

<build>
       <finalName>${project.artifactId}</finalName>
</build>

类似地,要从 settings.xml 文件中访问属性,可以使用“settings”前缀。最后,是“包络”前缀可用于访问环境变量值。例如${ env。PATH}将返回 PATH 环境变量的值。

用户定义的属性

Maven 允许您使用<properties />元素在pom.xml文件中声明定制属性。这些属性对于声明依赖版本非常有用。清单 4-8 显示了更新后的pom.xml文件,其中JUnit版本被声明为属性。当pom.xml有很多依赖项,并且你需要知道或者改变一个特定依赖项的版本时,这尤其有用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.apress.gswmbook</groupId>
   <!-- Removed for brevity -->

  <properties>
   <junit.version>4.12</junit.version>
  </properties>

  <developers>
    <!-- Removed for brevity -->
 </developers>
   <dependencies>
       <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>${junit.version}</version>
              <scope>test</scope>
       </dependency>
</dependencies>
</project>

Listing 4-8pom.xml File with Properties

摘要

Maven 的 CoC 为其所有项目规定了标准的目录布局。它提供了几个合理的目录,如src\main\javasrc\test,以及对每个目录中内容的建议。您了解了强制的pom.xml文件及其一些元素,它们用于配置 Maven 项目的行为。

在下一章中,您将看到 Maven 的生命周期、插件、构建阶段、目标,以及如何有效地利用它们。

五、Maven 生命周期

Maven 的核心是它的生命周期,它为构建和分发项目提供了统一的接口。在本章中,我们将回顾生命周期和构成生命周期的构件。

目标和插件

生成 JAR 或 WAR 文件等工件的构建过程通常需要几个步骤和任务,以便按照定义好的顺序成功完成。这种任务的例子包括编译源代码、运行单元测试以及工件的打包。Maven 使用目标的概念来表示这种粒度任务。

为了更好地理解什么是目标,让我们看一个例子。清单 5-1 显示了在C:\apress\gswm-book\chapter5\gswm下的gswm项目代码上执行的compile目标。顾名思义,compile目标编译源代码。compile目标识别src/main/java下的 Java 类HelloWorld.java,编译它,并将编译后的类文件放在target\classes文件夹下。

C:\apress\gswm-book\chapter5\gswm>mvn compiler:compile
[INFO] Scanning for projects...
[INFO] --- maven-compiler-plugin:3.1:compile (default-cli) @ gswm ---
[INFO] Compiling 1 source file to C:\apress\gswm-book\chapter5\gswm\target\classes
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------

Listing 5-1Maven compile Goal

Maven 中的目标被打包在插件中,这些插件本质上是一个或多个目标的集合。在清单 5-1 中,compiler是提供目标compile的插件。

清单 5-2 引入了一个非常漂亮的目标,叫做clean。如前所述,目标文件夹保存 Maven 生成的临时文件和工件。有时,目标文件夹会变得很大,或者缓存的某些文件需要从文件夹中清除。clean目标正好完成了这一点,因为它试图删除目标文件夹及其所有内容。

C:\apress\gswm-book\chapter5\gswm>mvn clean:clean
[INFO] Scanning for projects...
[INFO] --- maven-clean-plugin:2.5:clean (default-cli) @ gswm ---
[INFO] Deleting C:\apress\gswm-book\chapter5\gswm\target
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------

Listing 5-2Maven clean Goal

注意,清单 5-2 中命令clean:clean的格式。冒号(:前的clean代表clean插件,冒号后的clean代表clean目标。到目前为止,在命令行中运行目标显然需要以下语法:

mvn plugin_identifier:goal_identifier

Maven 提供了一个现成的帮助插件,可以用来列出给定插件中的可用目标。清单 5-3 显示了帮助插件的describe目标,以显示编译器插件内部的目标。

mvn help:describe -Dplugin=compiler

[INFO] Scanning for projects...
Name: Apache Maven Compiler Plugin
Description: The Compiler Plugin is used to compile the sources of your project.
Group Id: org.apache.maven.plugins
Artifact Id: maven-compiler-plugin
Version: 3.8.1
Goal Prefix: compiler

This plugin has 3 goals:

compiler:compile
  Description: Compiles application sources

compiler:help
  Description: Display help information on maven-compiler-plugin.
  Call mvn compiler:help -Ddetail=true -Dgoal=<goal-name> to display parameter details.

compiler:testCompile
  Description: Compiles application test sources

.

Listing 5-3Maven Help Plug-in

插件及其行为可以使用pom.xml的插件部分进行配置。考虑这样一种情况,您想要强制您的项目必须用 Java 8 编译。从 3.8 版本开始,Maven 编译器插件针对 Java 1.6 编译代码。因此,您需要在pom.xml文件中修改这个插件的行为,如清单 5-4 所示。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <!-- Project details omitted for brevity -->

  <dependencies>
       <!-- Dependency details omitted for brevity -->
  </dependencies>

  <build>
   <plugins>
    <plugin>
       <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
         <source>1.8</source>
         <target>1.8</target>
      </configuration>
    </plugin>
    </plugins>
  </build>
</project>

Listing 5-4Plug-in Element in the pom.xml File

现在,如果您运行mvn compiler:compile命令,生成的类文件将是 Java 版。

注意

pom.xml中的<build />元素有一个非常有用的子元素叫做finalName。默认情况下,Maven 生成的工件的名称遵循<<project_artifiact_id>>-<<project_version>>格式。然而,有时您可能想要改变生成的工件的名称,而不改变artifactId。您可以通过将finalName元素声明为<finalName>new_name</finalName>来实现这一点。

生命周期和阶段

Maven 目标是细粒度的,通常执行一项任务。需要以有序的方式执行多个目标,以执行复杂的操作,例如生成工件或文档。Maven 通过生命周期和阶段抽象简化了这些复杂的操作,这样与构建相关的操作可以用少量的命令来完成。

Maven 的构建生命周期由一系列以相同顺序执行的阶段组成,独立于正在生产的工件。Maven 将生命周期中的各个阶段称为阶段。每个 Maven 项目都有以下三个内置的生命周期:

  • default :这个生命周期处理 Maven 项目的编译、打包和部署。

  • clean :这个生命周期处理从目标目录中删除临时文件和生成的工件。

  • 站点:这个生命周期处理文档的生成和站点的生成。

为了更好地理解构建生命周期及其阶段,让我们看看与默认生命周期相关的一些阶段:

  • validate :运行检查以确保项目是正确的,并且所有的依赖项都已下载并可用。

  • 编译:编译源代码。

  • 测试:使用框架运行单元测试。这一步不需要打包应用程序。

  • 打包:将编译好的代码组装成可分发的格式,比如 JAR 或者WAR

  • install :将打包的归档文件安装到本地存储库中。该归档文件现在可供在该机器上运行的任何项目使用。

  • deploy :将构建好的档案推到远程存储库中,供其他团队和团队成员使用。

Maven 生命周期是一个抽象的概念,不能直接执行。相反,您执行一个或多个阶段。例如,命令mvn package将执行默认生命周期的package阶段。除了明确定义生命周期中各个阶段的顺序之外,Maven 还会自动执行请求阶段之前的所有阶段。因此,当运行mvn package命令时,Maven 将运行所有之前的阶段,比如编译和测试。

每个阶段都需要执行许多任务。为此,每个阶段都与零个或多个目标相关联。该阶段只是将这些任务委派给相关的目标。图 5-1 显示了生命周期、阶段、目标和插件之间的关联。

img/332298_2_En_5_Fig1_HTML.jpg

图 5-1

生命周期、阶段、目标和插件之间的关联

一个 Maven 阶段没有任何相关联的目标是有效的。在这种情况下,Maven 将跳过阶段执行。这样的阶段为用户和第三方供应商提供了占位符,以关联他们的定制目标。

pom.xml文件中的<packaging />元素将自动为每个阶段分配正确的目标,无需任何额外的配置。记住这是 CoC 的一个好处。例如,如果 packaging 元素是jar,那么 package 阶段将被绑定到jar插件中的jar目标。类似地,对于一个WAR工件,pom.xml会将包绑定到war插件中的war目标。图 5-2 显示了与 WAR 项目相关的内部生命周期的一部分。

img/332298_2_En_5_Fig2_HTML.jpg

图 5-2

WAR 项目的默认生命周期

跳过测试

如前所述,当您运行包阶段时,测试阶段也会运行,所有的单元测试都会执行。如果在测试阶段有任何失败,构建就会失败。这是期望的行为。然而,有些时候,例如,当处理一个遗留项目时,您想要跳过编译和运行测试,以便您可以成功地构建一个项目。您可以使用maven.test.skip属性来实现这一点。以下是使用此属性的示例:

mvn package –Dmaven.test.skip=true

插件开发

为 Maven 开发定制插件非常简单。如前所述,插件只是目标的集合。因此,当我们谈论插件开发时,我们本质上是在谈论开发目标。在 Java 中,这些目标是使用 MOJOs 实现的,其中代表 Maven Old Java Object,它类似于 Java 的 Plain Old Java Object (POJO)。

本节解释如何在运行 Maven 命令的控制台上开发一个显示系统信息的SystemInfoPlugin,比如 Java 版本、操作系统等等。

让我们通过创建一个名为gswm-maven-plugin的 Maven Java 项目来开始这个插件开发,如图 5-3 所示。

img/332298_2_En_5_Fig3_HTML.jpg

图 5-3

用于插件开发的 Maven 项目

注意

在本章中,我们将手动创建插件项目。Maven 提供了一个 mavan-archetype-mojo ,它将启动您的插件开发。我们将在第六章中学习玛文的原型。

pom.xml文件的内容如清单 5-5 所示。请注意,包装类型是maven-plugin。我们添加了maven-plugin-apimaven-plugin-annotations依赖项,因为插件开发需要它们。我们将利用 Apache Commons Lang 来获取系统信息。因此,我们还添加了 Apache Commons Lang 3 依赖项。

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.apress.plugins</groupId>
  <artifactId>gswm-maven-plugin</artifactId>
  <version>1.0.0</version>
  <packaging>maven-plugin</packaging>
  <description>System Info Plugin</description>

  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

   <dependencies>
     <dependency>
         <groupId>org.apache.maven</groupId>
         <artifactId>maven-plugin-api</artifactId>
         <version>3.6.1</version>
     </dependency>
     <dependency>
    <groupId>org.apache.maven.plugin-tools</groupId>
    <artifactId>maven-plugin-annotations</artifactId>
    <version>3.6.0</version>
    <scope>provided</scope>
  </dependency>
  <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.9</version>
  </dependency>
   </dependencies>
   <!-- Use the latest version of Plugin  -->
   <build>
      <plugins>
             <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-plugin-plugin</artifactId>
                   <version>3.6.0</version>
             </plugin>
      </plugins>
    </build>

</project>

Listing 5-5The 
pom.xml

with Dependencies

开发过程的下一步是创建 MOJO。清单 5-6 显示了SystemInfoMojo的代码。@Mojo 注释将 systeminfo jo 类标记为一个 Mojo,目标名称为“system info”。执行方法包含目标逻辑。在 SystemInfoMojo 中,我们只是将几条系统信息记录到控制台。

package com.apress.plugins;

import org.apache.commons.lang3.SystemUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;

@Mojo( name = "systeminfo")
public class SystemInfoMojo extends AbstractMojo {

@Override
      public void execute() throws MojoExecutionException, MojoFailureException {
           getLog().info( "Java Home: " + SystemUtils.JAVA_HOME );
           getLog().info( "Java Version: "+ SystemUtils.JAVA_VERSION);
           getLog().info( "OS Name: " + SystemUtils.OS_NAME );
           getLog().info( "OS Version: " + SystemUtils.OS_VERSION );
           getLog().info( "User Name: " + SystemUtils.USER_NAME );
}
}

Listing 5-6SystemInfoMojo Java Class

这个过程的最后一步是在 Maven 存储库中安装插件。在根目录下运行mvn install命令,您应该会得到清单 5-7 中所示的输出。

C:\apress\gswm-book\chapter5\gswm-maven-plugin>mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] --------< com.apress.plugins:gswm-maven-plugin >--------
[INFO] Building gswm-maven-plugin 1.0.0
[INFO] -------------------[ maven-plugin ]---------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ gswm-maven-plugin

[INFO] java-annotations mojo extractor found 1 mojo descriptor.

[INFO] --- maven-install-plugin:2.4:install (default-install) @ gswm-maven-plugin ---
[INFO] Installing C:\apress\gswm-book\chapter5\gswm-maven-plugin\target\gswm-maven-plugin-1.0.0.jar to C:\Users\<<USER_NAME>>\.m2\repository\com\apress\plugins\gswm-plugin\1.0.0\gswm-maven-plugin-1.0.0.jar
[INFO] Installing C:\apress\gswm-book\chapter5\gswm-maven-plugin\pom.xml to C:\Users\<<USER_NAME>>\.m2\repository\com\apress\plugins\gswm-maven-plugin\1.0.0\gswm-maven-plugin-1.0.0.pom

[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS

Listing 5-7Maven install Command

现在您已经准备好开始使用这个插件了。记住运行任何目标的语法是mvn pluginId:goal-name。清单 5-8 展示了这个插件的运行。请注意控制台上显示的系统信息。

C:\apress\gswm-book\chapter5\gswm-plugin>mvn com.apress.plugins:gswm-maven-plugin:systeminfo
[INFO] Scanning for projects...
[INFO] --- gswm-maven-plugin:1.0.0:systeminfo (default-cli) @ gswm-maven-plugin ---
[INFO] Java Home: C:\java\jdk-11
[INFO] Java Version: 11.0.1
[INFO] OS Name: Windows
[INFO] OS Version: 10
[INFO] User Name: Balaji
[INFO] --------------------------------------------------------

Listing 5-8Running the 
SystemInfoMojo

Plug-in

新开发的插件也可以用于其他 Maven 项目。清单 5-9 显示了将 systeminfo 目标附加到验证阶段的 POM 文件的一部分。

<project>
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.apress.plugins</groupId>
       <artifactId>gswm-plugin-test</artifactId>
       <version>1.0.0</version>
       <packaging>jar</packaging>
       <description>Plugin Test</description>

       <properties>
              <maven.compiler.source>1.8</maven.compiler.source>
              <maven.compiler.target>1.8</maven.compiler.target>
       </properties>

       <dependencies />

       <build>
             <plugins>
                   <plugin>
                          <groupId>com.apress.plugins</groupId>
                          <artifactId>gswm-maven-plugin</artifactId>
                          <version>1.0.0</version>
                          <executions>
                                <execution>

                                       <phase>validate</phase>
                                       <goals>
                                            <goal>systeminfo</goal>
                                       </goals>
                                </execution>
                          </executions>
                   </plugin>
             </plugins>
       </build>

</project>

Listing 5-9POM File Using systeminfo Goal

当 Maven 阶段(如 compile 或 package)被调用时,您将看到 systeminfo 目标的输出,如清单 5-10 所示。

mvn compile
[INFO] Scanning for projects...
[INFO] Building gswm-plugin-test 1.0.0
[INFO] Java Home: C:\java\jdk-11
[INFO] Java Version: 11.0.1
[INFO] OS Name: Windows
[INFO] OS Version: 10
[INFO] User Name: Balaji
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ gswm-plugin-test ---

Listing 5-10Compile Phase Output

摘要

Maven 使用基于插件的架构,这使得它的功能很容易扩展。每个插件都是一个或多个目标的集合,可以用来执行任务,比如编译源代码或运行测试。Maven 将目标与阶段联系起来。阶段通常作为构建生命周期的一部分按顺序执行。您还学习了创建插件的基础知识。

在下一章中,将向您介绍原型并了解多模块项目。

六、Maven 原型

到目前为止,您已经手动创建了 Maven 项目,生成文件夹并从头开始创建pom.xml文件。这可能会变得很乏味,尤其是当您经常需要创建项目时。为了解决这个问题,Maven 提供了原型。Maven 原型是允许用户轻松生成新项目的项目模板。

Maven 原型还提供了一个很好的平台来共享最佳实践,并在 Maven 的标准目录结构之外加强一致性。例如,企业可以用公司的品牌级联样式表(CSS)、批准的 JavaScript 库和可重用组件创建原型。使用这种原型来生成项目的开发人员将自动符合公司的标准。

内在原型

Maven 提供了数百种开箱即用的原型供开发人员使用。此外,许多开源项目提供了额外的原型供您下载和使用。Maven 还提供了一个原型插件,其目标是创建新的原型,并从现有的原型生成项目。

原型插件的generate目标允许您查看和选择要使用的原型。清单 6-1 显示了在命令行运行generate目标的结果。在写这本书的时候,有几千个原型可供选择。这一章将着眼于使用其中的一些原型。

$mvn archetype:generate
[INFO] Scanning for projects...

[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> am.ik.archetype:elm-spring-boot-blank-archetype (Blank multi project for Spring Boot + Elm)
2: remote -> am.ik.archetype:maven-reactjs-blank-archetype (Blank Project for React.js)
3: remote -> am.ik.archetype:msgpack-rpc-jersey-blank-archetype (Blank Project for Spring Boot + Jersey)

...........................
...........................

2460: remote -> ws.osiris:osiris-archetype (Maven Archetype for Osiris)
2461: remote -> xyz.luan.generator:xyz-gae-generator (-)
2462: remote -> xyz.luan.generator:xyz-generator (-)
2463: local -> com.inflinx.book.ldap:practical-ldap-empty-archetype (-)
2464: local -> com.inflinx.book.ldap:practical-ldap-archetype (-)

2465: local -> com.apress.gswm:gswm-web-archetype (gswm-web-archetype)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1398:

Listing 6-1Maven generate Goal

生成 Web 项目

Maven 为生成 web 应用程序提供了maven-archetype-webapp原型。让我们通过在C:\apress\gswm-book\chapter6文件夹中运行以下命令来生成应用程序:

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

该命令以交互模式运行。为请求的输入输入以下信息:

Define value for property 'groupId': : com.apress.gswmbook
Define value for property 'artifactId': : gswm-web
Define value for property 'version':  1.0-SNAPSHOT: :  <<Hit Enter>>
Define value for property 'package':  com.apress.gswmbook: : war

Confirm the properties configuration:
groupId: com.apress.gswmbook
artifactId: gswm-web
version: 1.0-SNAPSHOT
package: war
 Y: <<Hit Enter>>

生成的目录结构应该如图 6-1 所示。

img/332298_2_En_6_Fig1_HTML.jpg

图 6-1

Maven web 项目结构

pom.xml文件是最小的,只有一个 JUnit 依赖项。Maven 使得使用嵌入式 web 服务器(如 Tomcat 和 Jetty)运行 web 应用程序变得更加容易。清单 6-2 显示了添加了 Jetty 插件的修改后的pom.xml文件。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm-web</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>gswm-web Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>gswm-web</finalName>
    <plugins>
      <plugin>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-maven-plugin</artifactId>
          <version>9.4.12.RC2</version>
       </plugin>
    </plugins>
  </build>
</project>

Listing 6-2Modified pom.xml with Embedded Jetty Plug-in

为了使用 Jetty server 启动 web 应用程序,请在项目的根目录下运行以下命令:

mvn jetty:run

您将看到项目被部署,并看到类似于清单 6-3 所示的输出。

[INFO] Started o.e.j.m.p.JettyWebAppContext@e38f0b7{Archetype Created Web Application,/,file: C:/apress/gswm-book/chapter6/gswm-web/src/main/webapp/,AVAILABLE}{file:///C:/apress/gswm-book/chapter6/gswm-web/src/main/webapp/}
[INFO] Started ServerConnector@5a0e0886{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[INFO] Started @5120ms
[INFO] Started Jetty Server

Listing 6-3Output from the Jetty run Command

现在启动浏览器并导航至http://localhost:8080/。你应该会看到如图 6-2 所示的网页。

img/332298_2_En_6_Fig2_HTML.jpg

图 6-2

在浏览器中启动的 Web 项目

多模块项目

Java 企业版(JEE)项目通常被分成几个模块,以便于开发和维护。这些模块中的每一个都产生诸如 Enterprise JavaBean s(EJB)、web 服务、web 项目和客户端等构件。Maven 通过允许多个 Maven 项目嵌套在单个 Maven 项目下来支持这种大型 JEE 项目的开发。这样一个多模块项目的布局如图 6-3 所示。父项目有一个pom.xml文件,里面有单独的 Maven 项目。

img/332298_2_En_6_Fig3_HTML.png

图 6-3

多模块项目结构

在本节的剩余部分中,我们将解释如何构建一个多模块项目,在这种情况下,您必须将您的大型项目分成提供用户界面的 web 应用程序(WAR工件)、保存服务层代码的服务项目(JAR工件)和保存存储库层代码的持久性项目。图 6-4 提供了该场景的可视化表示。

img/332298_2_En_6_Fig4_HTML.jpg

图 6-4

Maven 多模块项目

让我们从生成父项目开始这个过程。为此,在命令行的C:\apress\gswm-book\chapter6下运行以下命令:

mvn archetype:generate -DgroupId=com.apress.gswmbook -DartifactId=gswm-parent -Dversion=1.0.0-SNAPSHOT -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=pom-root

原型pom-root创建了gswm-parent文件夹和它下面的pom.xml文件。正如您在清单 6-4 中看到的,生成的pom.xml文件只有最少的内容。请注意,父项目的打包设置为类型pom

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm-parent</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>gswm-parent</name>
</project>

Listing 6-4Parent pom.xml File

然后通过在C:\apress\gswm-book\chapter6\gswm-parent文件夹中运行以下命令来创建 web 项目:

mvn archetype:generate -DgroupId=com.apress.gswmbook -DartifactId=gswm-web -Dversion=1.0.0-SNAPSHOT -Dpackage=war -DarchetypeArtifactId=maven-archetype-webapp

在这个 web 项目生成过程中,您将提供 Maven 坐标,比如 groupId、version 等等,作为generate目标的参数。这就产生了gswm-web项目。

下一步是创建service项目。在C:\apress\gswm-book\chapter6\gswm-parent下运行以下命令:

mvn archetype:generate -DgroupId=com.apress.gswmbook -DartifactId=gswm-service -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

注意,您没有提供 package 参数,因为默认情况下,maven-archetype-quickstart会生成一个 JAR 项目。另外,请注意interactiveMode参数的使用。这指示 Maven 简单地运行命令,而不提示用户输入。

与上一步类似,通过在C:\apress\gswm-book\chapter6\gswm-parent下运行以下命令,创建另一个 Java 项目gswm-repository:

mvn archetype:generate -DgroupId=com.apress.gswmbook -DartifactId=gswm-repository -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

现在您已经生成了所有的项目,让我们看看gswm-parent下的pom.xml文件。清单 6-5 显示了pom.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm-parent</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>gswm-parent</name>
  <modules>
    <module>gswm-web</module>
    <module>gswm-service</module>
    <module>gswm-repository</module>
  </modules>
</project>

Listing 6-5Parent pom.xml File with Modules

元素允许你在一个多模块项目中声明子模块。当您生成每个模块时,Maven 智能地将它们注册为子模块。此外,它修改了单个模块的pom.xml文件,并添加了父模块的pom信息。清单 6-6 显示了带有父pom元素的gswm-web项目的pom.xml文件。

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.apress.gswmbook</groupId>
    <artifactId>gswm-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
  </parent>
  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm-web</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>gswm-web Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>gswm-web</finalName>
  </build>
</project>

Listing 6-6The pom.xml File for the Web Module

设置好所有的基础设施后,您就可以开始构建下一个项目了。为此,只需运行gswm-project下的mvn package命令,如清单 6-7 所示。

C:\apress\gswm-book\chapter6\gswm-parent>mvn package
[INFO] Scanning for projects...
[INFO] --------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] gswm-parent
[INFO] gswm-web Maven Webapp
[INFO] gswm-service
[INFO] gswm-repository
[INFO] --------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] gswm-parent .......................... SUCCESS [0.001s]
[INFO] gswm-web Maven Webapp ................ SUCCESS [1.033s]
[INFO] gswm-service ......................... SUCCESS [0.552s]
[INFO] gswm-repository ...................... SUCCESS [0.261s]
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------

Listing 6-7Maven Package Run on the Parent Project

创造原型

Maven 提供了几种创建新原型的方法。这里我们将使用一个现有的项目来生成一个原型。

让我们从创建一个原型项目开始,您将使用它作为原型创建的种子。这个项目将与 Servlet 4.0 兼容,并且有一个返回 HTTP 状态代码 200 的状态 Servlet。不是从头开始创建一个 web 项目,而是复制先前生成的gswm-web项目代码并在C:\apress\gswm-book\chapter6下创建gswm-web-prototype。对新拷贝的项目进行以下更改:

  1. 移除目标文件夹和其他资源,比如特定于集成开发环境(IDE)的文件(.project.classpath等等),这些都是您不希望在原型中终止的。

  2. 用下面的代码替换webapp/WEB-INF文件夹下web.xml文件的内容。这将升级 web 应用程序以使用 Servlet 4.0。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="4.0"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
       http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
    
         <display-name>Archetype Created Web Application</display-name>
    </web-app>
    
    
  3. 将 Servlet 4.0 依赖项添加到pom.xml文件中。更新后的pom.xml如清单 6-8 所示。

  4. 因为您将进行 Java web 开发,所以在src/main下创建一个名为java的文件夹。同样,在src下创建test/javatest/resources文件夹。

  5. src/main/java下的com.apress.gswmbook.web.servlet包中创建AppStatusServlet.java文件。包com.apress.gswmbook.web.servlet转化为文件夹结构com\apress\gswmbook\web\servlet。清单 6-9 中显示了AppStatusServlet.java的源代码。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.apress.gswmbook</groupId>
  <artifactId>gswm-web</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>gswm-web Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
       <artifactId>javax.servlet-api</artifactId>
       <version>4.0.1</version>
       <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>gswm-web</finalName>
    <plugins>
      <plugin>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-maven-plugin</artifactId>
       <version>9.4.12.RC2</version>
       </plugin>
    </plugins>
  </build>
</project>

Listing 6-8The pom.xml with Servlet Dependency

package com.apress.gswmbook.web.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.∗;
import javax.servlet.http.∗;
import java.io.∗;

@WebServlet("/status")
public class AppStatusServlet extends HttpServlet {

      public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        PrintWriter writer = response.getWriter();
        writer.println("OK");
        response.setStatus(response.SC_OK);
    }

}

Listing 6-9AppStatusServlet Java Class Source Code

原型项目将类似于图 6-5 所示的结构。

img/332298_2_En_6_Fig5_HTML.jpg

图 6-5

生成的原型项目

使用命令行,导航到项目文件夹 g swm-web-prototype并运行以下命令:

mvn archetype:create-from-project

完成该命令后,您应该会看到消息原型在目标/生成的源/原型中创建。新创建的原型现在位于gswm-web-prototype/target/generated-sources/archetype下。

下一步是将新创建的原型移动到一个单独的文件夹gswm-web-archetype中,以便在发布之前可以对其进行调整。为此,请按照下列步骤操作:

  1. C:\apress\gswm-book\chapter6文件夹中创建文件夹gswm-web-archetype

  2. 将 pom.xml 和 src 目录及其文件从C:\apress\gswm-book\chapter6\gswm-web-prototype\target\generated-sources\archetype文件夹复制到gswm-web-archetype文件夹。

gswm-web-archetype的目录结构应类似于图 6-6 所示。

img/332298_2_En_6_Fig6_HTML.jpg

图 6-6

Web 原型项目结构

让我们从位于gswm-web-archetype文件夹根目录下的pom.xml文件开始修改过程。将 pom 文件中的 artifactId 更改为“gswm-web-archetype”。接下来,我们将修改位于gswm-web-archetype\src\main\resources\archetype-resources的 pom.xml 文件。在项目创建期间,将 pom.xml文件中的gswm-web更改为${artifactId}.,Maven 将用用户提供的artifactId值替换${artifactId}表达式。

当从原型创建项目时,Maven 会提示用户输入包名。它将在新创建的项目的src/main/java文件夹下创建对应于该包的目录。然后,它将原型的archetype-resources/src/main/java文件夹下的所有内容移动到那个包中。因为您想要子包web.servlet下的AppStatusServlet,所以创建文件夹web/servlet并将AppStatusServlet.java移动到新创建的文件夹下。AppStatusServlet.java的新位置如图 6-7 所示。

img/332298_2_En_6_Fig7_HTML.jpg

图 6-7

AppStatusServletweb.servlet包下

打开AppStatusServlet.java,将包名从package ${package};改为package ${package}.web.servlet;

创建原型的最后一步是在命令行运行文件夹gswm-web-archetype中的以下内容:

mvn clean install

使用原型

一旦原型被安装,从它创建一个项目的最简单的方法是在C:\apress\gswm-book\chapter6下运行下面的命令:

mvn archetype:generate -DarchetypeCatalog=local

为 Maven 提示符输入清单 6-10 中所示的值,您将看到一个test-project被创建。

C:\apress\gswm-book\chapter6>mvn archetype:generate -DarchetypeCatalog=local
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------------------------------
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:1: local -> com.apress.gswmbook:gswm-web-archetype (gswm-web-archetype)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
Define value for property 'groupId': : com.apress.gswmbook
Define value for property 'artifactId': : test-project
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  com.apress.gswmbook: :
Confirm properties configuration:
groupId: com.apress.gswmbook
artifactId: test-project
version: 1.0-SNAPSHOT
package: com.apress.gswmbook
 Y: :
---------------------------------------------------------------
project
[INFO] --------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------

Listing 6-10Creating a New Project Using Archetype

因为test-projectpom.xml文件已经嵌入了 Jetty 插件,所以在命令行中运行文件夹C:\apress\gswm-book\chapter6\test-project下的mvn jetty:run来启动项目。打开浏览器,导航至http://localhost:8080/status。您将看到显示字符串 OK。

摘要

Maven 原型是项目模板,允许您快速启动新项目。本章使用内置原型来生成高级 Maven 项目,例如 web 项目和多模块项目。您还了解了如何创建和使用定制原型。

在下一章中,您将学习使用 Maven 生成站点以及创建文档和报告的基础知识。

七、文件和报告

文档和报告是任何项目的关键方面。对于企业和开源项目来说尤其如此,在这些项目中,许多人合作开发项目。本章介绍了 Maven 的一些工具和插件,它们使得在线文档的发布和维护变得轻而易举。

在本章中,您将再次使用您在前面章节中构建的gswm Java 项目。在C:\apress\gswm-book\chapter7文件夹中也可以找到gswm项目。

使用站点生命周期

正如在第五章中所讨论的,Maven 提供了站点生命周期,可以用来生成项目的文档。让我们从gswm目录运行以下命令:

mvn site

站点生命周期使用 Maven 的站点插件来生成项目的站点。此命令完成后,将在项目的目标文件夹下创建一个站点文件夹。图 7-1 显示了站点文件夹的内容。

img/332298_2_En_7_Fig1_HTML.jpg

图 7-1

生成的网站文件夹

在浏览器中打开index.html文件,查看生成的站点。Maven 自动将默认皮肤应用于站点,并生成相应的图像和 CSS 文件。图 7-2 显示了生成的index.html文件。

img/332298_2_En_7_Fig2_HTML.jpg

图 7-2

生成的索引页面

单击左侧导航栏底部的“依赖关系”链接,您将进入“项目依赖关系”页面。“项目相关性”页面提供了关于项目的直接和传递相关性的有价值的信息。它还提供与这些依赖项相关的许可信息,如图 7-3 所示。

img/332298_2_En_7_Fig3_HTML.jpg

图 7-3

项目相关性页面

Maven 允许您向 pom.xml 文件添加信息,以便生成的站点包含有用的信息。清单 7-1 显示了更新后的 pom.xml 文件。为了成功生成站点,我们明确声明了最新版本的 maven-site-plugin。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.apress.gswmbook</groupId>

  <artifactId>gswm</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Getting Started with Maven</name>
  <url>http://apress.com</url>

  <description>
    This project acts as a starter project for the Introducing Maven book (http://www.apress.com/9781484208427) published by Apress.
  </description>

  <mailingLists>
    <mailingList>
      <name>GSWM Developer List</name>
      <subscribe>gswm-dev-subscribe@apress.com</subscribe>
      <unsubscribe>gswm-dev-unsubscribe@apress.com</unsubscribe>
      <post>developer@apress.com</post>
    </mailingList>
  </mailingLists>

  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
    </license>
  </licenses>

  <!--- Developer and Dependency removed for brevity --->
   <build>
   <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
         <source>1.8</source>
         <target>1.8</target>
      </configuration>
    </plugin>
    <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.8.2</version>
      </plugin>
  </plugins>
</build>

</project>

Listing 7-1The pom.xml File with Project Information

在清单 7-1 中,我们使用description元素来提供项目的描述。mailingList元素是关于与项目相关的不同邮件列表的信息,license元素包括项目的许可。有了更新的 pom.xml 文件,让我们通过运行以下命令重新生成站点:

mvn clean site

启动新生成的target\site文件夹下的index.html文件。图 7-4A 和 7-4B 分别显示了新的关于和项目许可页面。注意,Maven 使用在license元素中声明的 URL 来下载许可文本,并将其包含在生成的网站中。

img/332298_2_En_7_Fig5_HTML.jpg

图 7-4B

生成的项目许可证页面

img/332298_2_En_7_Fig4_HTML.jpg

图 7-4A

生成的关于页面

高级站点配置

在前面的小节中,项目信息是在pom.xml文件中指定的,供 Maven 在站点生成期间使用。对于较大的项目,这种方法会导致臃肿且难以维护的pom.xml文件。此外,企业通常更喜欢在生成的站点中使用他们的品牌和徽标,而不是默认的 Maven 皮肤。为了解决这些问题,Maven 允许您在名副其实的src/site文件夹下为站点生成指定内容和配置。图 7-5 显示了一个简单站点文件夹的目录结构。

img/332298_2_En_7_Fig6_HTML.jpg

图 7-5

站点文件夹目录结构

site.xml文件,也称为站点描述符,用于定制生成的站点。我们马上就会看到这个文件。

apt文件夹包含以几乎纯文本 (APT)格式编写的网站内容。APT 格式允许以类似于纯文本的语法创建文档。关于 APT 格式的更多信息可以在 Maven 网站上找到( http://maven.apache.org/doxia/references/apt-format.html )。除了 APT,Maven 还支持其他格式,比如 FML、Xdoc 和 Markdown。

Maven 提供了几个原型,允许您自动生成站点结构。要更新现有的 gswm 项目,请在C:\apress\gswm-book\chapter7\gswm文件夹中运行以下命令。出现提示时,输入 groupId、artifactId 和 package 的值。

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-site-simple -DarchetypeVersion=1.4

Define value for property 'groupId': : com.apress.gswmbook
Define value for property 'artifactId': : gswm
Define value for property 'version':  1.0-SNAPSHOT: : 1.0.0-SNAPSHOT
Define value for property 'package':  com.apress.gswmbook: :  <<Press Enter>>

成功完成该命令后,您将看到在gswm\src下创建的站点文件夹,带有site.xmlapt文件夹。让我们从添加项目描述到index.apt.开始,用清单 7-2 中的代码替换index.apt文件的内容。

-----
 Getting Started with Maven
 -----
 Apress
 -----
 08-10-2019
 -----

This project acts as a starter project for the Introducing Maven book published by Apress. For more information, check out the Apress site: www.apress.com.

Listing 7-2The index.apt File Contents

前三个部分包含文档的标题、作者和日期。以下文本块包含项目描述。运行mvn clean site会产生一个新的关于页面,如图 7-6 所示。

img/332298_2_En_7_Fig7_HTML.jpg

图 7-6

关于包含新内容的页面

site.xml 文件允许您定制生成的站点,例如更改标题和覆盖默认导航和外观。为了更好地理解 site.xml 的功能,让我们更改生成的站点徽标。静态资产,如图像和 HTML 文件,放在site/resources文件夹中。当 Maven 构建站点时,它将resources文件夹中的资产复制到生成的站点的根目录。从C:\apress\gswm-book\chapter7文件夹中复制公司 logo company.png,放入gswm/src/site/resources/images文件夹中。

用清单 7-3 的内容替换site.xml文件。注意,徽标的src元素包括相对路径img/company.pngmenu元素用于创建到您想要包含在站点中的定制网页/内容/Wiki 页面的链接。

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="${artifactId}"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0 http://maven.apache.org/xsd/decoration-1.8.0.xsd">
  <bannerLeft>
    <name>Apress</name>
    <src>img/company.png</src>
    <href>http://apress.com</href>
  </bannerLeft>

  <skin>
    <groupId>org.apache.maven.skins</groupId>
    <artifactId>maven-fluido-skin</artifactId>
    <version>1.7</version>
  </skin>

  <body>
    <links>
      <item name="Maven" href="https://maven.apache.org/"/>
    </links>

    <menu name="Documentation">
      <item name="Apache Site" href="http://www.apache.org"/>
    </menu>

    <menu ref="reports" />
  </body>
</project>

Listing 7-3The site.xml File Contents

运行mvn clean site生成带有新 logo 和附加导航项的站点,如图 7-7 所示。

img/332298_2_En_7_Fig8_HTML.jpg

图 7-7

关于带有新徽标的页面

生成 Javadoc 报告

Javadoc 是记录 Java 代码的事实上的标准。它帮助开发人员理解一个类或一个方法做什么。Javadoc 还突出显示了不推荐使用的类、方法或字段。

Maven 提供了一个 Javadoc 插件,它使用 Javadoc 工具来生成 Javadoc。集成 Javadoc 插件只需要在pom.xml文件的reporting元素中声明它,如清单 7-4 所示。在pom reporting元素中声明的插件在站点生成期间被执行。

<project>
        <!—Content removed for brevity-->
 <reporting>
    <plugins>
      <plugin>
                <artifactId>maven-javadoc-plugin</artifactId>
      </plugin>
    </plugins>
  </reporting>
</project>

Listing 7-4The pom.xml Snippet with Javadoc Plug-in

现在您已经配置了 Javadoc 插件,让我们运行mvn clean site来生成 Javadoc。命令成功运行后,您会注意到在gswm /target/site下创建的apidocs文件夹。启动site下的index.html文件,导航到项目报告➤ Javadoc。图 7-8 显示了为gswm项目生成的 Javadoc。

img/332298_2_En_7_Fig9_HTML.jpg

图 7-8

生成的 Javadoc 页面

生成单元测试报告

测试驱动开发已经成为当今企业的规范。单元测试向开发人员提供即时反馈,并允许他们构建高质量的代码。考虑到测试的重要性,Maven 为每个构建执行所有的测试。任何测试失败都会导致构建失败。

Maven 提供了 Surefire 插件,该插件为运行由 JUnit 或 TestNG 等框架创建的测试提供了统一的接口。它还生成各种格式的执行结果,如 XML 和 HTML。这些发布的结果使开发人员能够快速找到并修复损坏的测试。

Surefire 插件的配置方式与pom文件的reporting部分中的 Javadoc 插件相同。清单 7-5 显示了 Surefire 插件的配置。

<project>
        <!—Content removed for brevity-->
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
        <version>2.17</version>
      </plugin>
    </plugins>
  </reporting>
</project>

Listing 7-5The pom.xml Snippet with Surefire Plug-in

现在 Surefire 已经配置好了,让我们通过运行 mvn clean site command来生成一个 Maven 站点。成功执行该命令后,您会看到在gswm\target下生成了一个Surefire Reports文件夹。它包含 XML 和 TXT 格式的测试执行结果。相同的信息将以 HTML 格式保存在site文件夹下的surefire-report.html文件中。启动网站下的 index.html 文件,并导航到项目报告➤ Surefire 报告。图 7-9 显示了gswm项目的万无一失报告。

img/332298_2_En_7_Fig10_HTML.jpg

图 7-9

生成的 Surefire 报告

生成代码覆盖率报告

代码覆盖率是对自动化测试使用了多少源代码的度量。本质上,它提供了测试质量的指示。 JaCoCo (开源)和 Atlassian 的 Clover 是两个流行的 Java 代码覆盖工具。

在本节中,您将使用 JaCoCo 来度量这个项目的代码覆盖率。清单 7-6 显示了 JaCoCo 插件的配置。prepare-agent 目标设置一个指向 JaCoCo 运行时环境的属性,该属性在单元测试运行时作为 VM 参数传递。报告目标在单元测试执行完成后生成代码覆盖报告。

<project>
        <build>
           <plugins>
               <!--Content removed for brevity-->
               <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                        <version>0.8.4</version>
                        <executions>
                           <execution>
                       <id>jacoco-init</id>
                               <goals>
                                   <goal>prepare-agent</goal>
                               </goals>
                           </execution>
                           <execution>
                                <id>jacoco-report</id>
                                <phase>test</phase>
                                 <goals>
                               <goal>report</goal>
                                 </goals>
                           </execution>
                       </executions>
                       </plugin>
                  </plugins>
            <build>
</project>

Listing 7-6The pom.xml Snippet

with the JaCoCo Plug-in

现在插件已经配置好了,让我们使用mvn clean site命令生成站点。成功完成该命令后,JaCoCo 将在gswm\target\site下创建一个jacoco文件夹。双击 jacoco 文件夹下的index.html文件,启动代码覆盖报告。该报告应类似于图 7-10 所示的报告。

img/332298_2_En_7_Fig11_HTML.jpg

图 7-10

生成的 JaCoCo 报告

生成 SpotBugs 报告

SpotBugs 是一个检测 Java 代码缺陷的工具。它使用静态分析来检测 bug 模式,比如无限递归循环和空指针取消引用。清单 7-7 显示了 SpotBugs 的配置。

<project>
        <!—Content removed for brevity-->
  <reporting>
    <plugins>
      <plugin>
        <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>3.1.12</version>
      </plugin>
   </plugins>
 </reporting>
</project>

Listing 7-7The pom.xml Snippet with SpotBugs Plug-in

一旦 Maven 站点生成,打开site文件夹下的index.html文件,导航到项目报告➤ SpotBugs 查看 SpotBugs 报告。它应该与图 7-11 所示的相似。

img/332298_2_En_7_Fig12_HTML.png

图 7-11

已生成 SpotBugs Bug 检测器报告

摘要

Maven 提供的文档和报告功能在创建可维护的高质量软件中扮演着重要的角色。本章解释了使用站点生命周期的基础知识以及制作文档所需的配置。您还了解了如何生成 Javadocs、测试覆盖率和 SpotBugs 报告。

在下一章,我们将解释如何将 Maven 与 Nexus 和 Git 集成。您还将了解 Maven 的发布过程。

八、Maven 版本

Maven 提供了一个发布插件,可以自动完成发布软件的步骤。在我们深入研究 Maven 发布过程之前,我们将设置和配置 Nexus 存储库,并使用 Maven 向 Nexus 发布工件。

与 Nexus 的集成

存储库管理器是企业中 Maven 部署的关键部分。存储库管理人员充当公共存储库的代理,促进工件共享和团队协作,确保构建稳定性,并支持企业中使用的工件的治理。

sonatypeNexusrepository manager 是一款流行的开源软件,允许您维护内部存储库和访问外部存储库。它允许通过单一 URL 对存储库进行分组和访问。这使得存储库管理员能够在后台添加和删除新的存储库,而不需要开发人员更改他们计算机上的配置。此外,它还为使用 Maven 站点和工件搜索功能生成的站点提供托管功能。

在我们研究将 Maven 与 Nexus 集成之前,您需要在本地机器上安装 Nexus。Nexus 是作为一个归档分发的,它与一个 Jetty 实例捆绑在一起。从 Sonatype 的网站 https://help.sonatype.com/repomanager3/download 下载 Nexus 发行版(【Windows 版)。在撰写本文时,Nexus 的 3.18.1-01 版本已经发布。解压缩文件,并将内容放在您的机器上。在本书中,我们假设内容在C:\tools\nexus folder下。

注意

大多数企业通常在中央服务器上安装并提供存储库管理器。如果您已经可以访问存储库管理器,请跳过安装的这一部分。

管理员模式下启动你的命令行,导航到C:\tools\nexus\nexus-3.18.1-01下的 bin 文件夹。然后运行命令nexus /install Nexus_Repo_Manager。您将看到如图 8-1 所示的成功消息。

img/332298_2_En_8_Fig1_HTML.jpg

图 8-1

安装 Nexus 时的成功消息

注意

Nexus 3.18 需要 JRE 8 才能正常工作。确保您的本地计算机上安装了 JDK/JRE 版本 8。此外,确保JAVA_HOME指向 JDK 的版本 8。

在同一个命令行上,运行命令nexus start来启动 Nexus。图 8-2 显示了运行该命令的结果。

img/332298_2_En_8_Fig2_HTML.jpg

图 8-2

起始关系

默认情况下,Nexus 运行在端口 8081 上。启动网络浏览器并导航至位于http://localhost:8081/的 Nexus。这将需要几分钟,但最终你应该会看到 Nexus 启动屏幕,如图 8-3 所示。

img/332298_2_En_8_Fig3_HTML.jpg

图 8-3

Nexus 启动屏幕

点击右上角的“登录”链接,登录 Nexus。您将看到一个登录模式,其中包含自动生成的管理员密码文件的位置,如图 8-4 所示。

img/332298_2_En_8_Fig4_HTML.png

图 8-4

Nexus 登录模式

使用从 admin.password 文件中复制的用户名 admin 和密码登录 Nexus。您将被要求更改密码,如图 8-5 所示。对于本书中的练习,我将密码改为 admin123。

img/332298_2_En_8_Fig5_HTML.jpg

图 8-5

Nexus 更改密码屏幕

现在 Nexus 已经安装并运行了,让我们修改位于C:\apress\gswm-book\chapter8下的gwsm项目。您将从在pom.xml文件中添加一个distributionManagement元素开始,如清单 8-1 所示。该元素用于提供关于项目工件将被部署到哪里的存储库信息。repository子元素指出了发布的工件将被部署的位置。类似地,snapshotRepository元素标识了存储项目快照版本的位置。

<project  xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <dependencies>
            <!-- Content removed for brevity -->
        </dependencies>
        <distributionManagement>
           <repository>
              <id>nexusReleases</id>
              <name>Releases</name>
        <url>http://localhost:8081/repository/maven-releases</url>
           </repository>
           <snapshotRepository>
              <id>nexusSnapshots</id>
              <name>Snapshots</name>
              <url>http://localhost:8081/repository/maven-snapshots</url>
           </snapshotRepository>
        </distributionManagement>
        <build>
            <!-- Content removed for brevity -->
        </build>
</project>

Listing 8-1The pom.xml with distributionManagement

注意

开箱即用,Nexus 自带 R eleases和 S napshots库。默认情况下,快照工件将存储在Snapshots Repository中,而发布工件将存储在Releases存储库中。

像大多数存储库管理器一样,部署到 Nexus 是一个受保护的操作。为了让 Maven 在 Nexus 上交互和部署工件,您需要在 settings.xml 文件中为用户提供正确的访问角色。清单 8-2 显示了带有服务器信息的settings.xml文件。如您所见,我们使用管理员用户信息来连接 Nexus。注意,在服务器标签中声明的 id——nexusReleasesnexusSnapshots—必须与在pom.xml文件中声明的repositorysnapshotRepository的 id 相匹配。用清单 8-2 中的代码替换C:\Users\<<USER_NAME>>\.m2文件夹中settings.xml文件的内容。

<?xml version="1.0" encoding="UTF-8" ?>
<settings  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
   <server>
      <id>nexusReleases</id>
      <username>admin</username>
      <password>admin123</password>
   </server>
   <server>
      <id>nexusSnapshots</id>
      <username>admin</username>
      <password>admin123</password>
   </server>
</servers>
</settings>

Listing 8-2Settings.xml File with Server Information

与 Nexus 交互的配置步骤到此结束。在命令行,运行目录C:\apress\gswm-book\chapter8\gswm下的命令mvn deploy。成功执行该命令后,您会在http://localhost:8081/#browse/browse:maven-snapshots看到 Nexus 下的快照工件,如图 8-6 所示。

img/332298_2_En_8_Fig6_HTML.jpg

图 8-6

Nexus 下的快照工件

项目发布

发布项目是一个复杂的过程,通常包括以下步骤:

  • 验证本地计算机上没有未提交的更改。

  • pom.xml文件的版本中删除快照。

  • 确保项目没有使用任何快照依赖项。

  • 将修改后的pom.xml文件签入到您的源代码控制中。

  • 创建源代码的源代码控制标记。

  • 构建工件的新版本,并将其部署到存储库管理器。

  • 增加pom.xml文件中的版本,为下一个开发周期做准备。

Maven 有一个发布插件,它为执行前面的步骤和发布项目工件提供了一个标准机制。正如您所看到的,作为其发布过程的一部分,Maven 与源代码控制系统进行了大量的交互。在本节中,您将使用 Git 作为源代码控制系统,使用 GitHub 作为存储库的远程服务器。Maven 和 GitHub 之间的典型交互如图 8-7 所示。Maven 发布通常在开发人员或构建机器上执行。Maven 要求在这样的机器上安装 Git 客户端。这些命令行工具允许 Maven 与 GitHub 交互,并执行诸如签出代码、创建标签等操作。

img/332298_2_En_8_Fig7_HTML.jpg

图 8-7

Maven 和 GitHub 之间的交互

在我们深入研究 Maven 发布过程之前,您需要通过完成以下步骤来设置环境:

  1. 在本地机器上安装 Git 客户端。

  2. 在 GitHub 上创建一个新的远程资源库。

  3. 将您将要使用的项目登记到远程存储库中。

Git 客户端安装

有几个 Git 客户端使得与 Git 存储库的交互变得很容易。比较流行的有 SourceTree ( www.sourcetreeapp.com/ )和 GitHub Desktop ( https://desktop.github.com/ )。在本书中,我们将使用 Git SCM 发行版附带的客户端。导航到 https://git-scm.com/downloads 并下载 Git 发行版的 Windows 版本。双击下载的 exe 文件,接受默认安装选项。安装完成后,打开一个新的命令行窗口并键入 git - version。您应该会看到类似图 8-8 的消息。

img/332298_2_En_8_Fig8_HTML.jpg

图 8-8

Git 版本

创建 GitHub 存储库

GitHub 是一个协作开发平台,允许您免费托管公共和私有 Git 存储库。在 GitHub 上创建新的资源库之前,您需要在 https://github.com/join 创建一个帐户。使用您的凭证登录 GitHub 后,导航到 https://github.com/new 并创建一个新的存储库,如图 8-9 所示。

img/332298_2_En_8_Fig9_HTML.jpg

图 8-9

新的 GitHub 资源库

签入源代码

让您的环境为 Maven 发布做好准备的最后一步是将C:\apress\gswm-book\chapter8\gswm下的gswm项目签入到新创建的 remove 存储库中。使用您的命令行,导航到C:\apress\gswm-book\chapter8\gswm文件夹,并按顺序运行以下命令。通过在下面的 remote add 命令中替换您的 GitHub 帐户,确保您使用正确的远程存储库 URL:

  • git init

  • git add .

  • git commit -m "Initial commit"

  • git remote add origin https://github.com/<<your_git_hub_account>>/intro-maven.git

  • git push -u origin master

Git push 命令将提示您输入 GitHub 用户名和密码。push 命令的成功完成应给出如图 8-10 所示的输出。

img/332298_2_En_8_Fig10_HTML.jpg

图 8-10

来自Git初始提交的输出

使用您的浏览器,导航到您在 GitHub 上的远程存储库,您将看到签入的代码。图 8-11 显示了预期的浏览器屏幕。

img/332298_2_En_8_Fig11_HTML.jpg

图 8-11

项目已签入 GitHub

前面的命令已经将代码推入 GitHub 上的 mater 分支。但是,Maven 发布插件与发布分支中的代码进行交互。因此,这个设置的最后一步是创建一个新的本地发布分支,并通过运行以下命令将其推送到 GitHub:

  • git checkout –b release

  • git push origin release

Maven 版本

使用 Maven 的发布过程发布一个工件需要使用两个重要的目标:prepareperform。此外,release 插件提供了一个clean目标,在出现问题时可以派上用场。

准备目标

顾名思义,prepare目标是为发布准备一个项目。作为该阶段的一部分,Maven 执行以下操作:

  • check-poms :检查pom.xml文件中的版本是否有快照。

  • scm-check-modifications :检查是否有未提交的变更。

  • check-dependency-snapshots:检查pom文件,看是否有任何快照依赖。对于您的项目来说,使用已发布的依赖项是一种最佳实践。在pom.xml文件中发现的任何快照依赖关系都将导致发布失败。

  • 地图-发布-版本:在交互模式下运行prepare时,提示用户发布版本。

  • 地图-开发-版本:在交互模式下运行prepare时,提示用户下一个开发版本。

  • 生成-发布-poms :生成发布pom文件。

  • scm-commit-release :向 scm 提交pom文件的释放。

  • scm-tag :为 scm 中的代码创建一个发布标签。

  • rewrite-poms-for-development:为新的开发周期更新pom文件。

  • remove-release-poms :删除发布生成的pom文件。

  • scm-commit-development :提交带有开发版本的pom.xml文件。

  • 最终释放:完成释放的prepare阶段。

为了方便起见,您应该在项目的pom.xml文件中提供配置管理信息。清单 8-3 显示了带有 SCM 信息的pom.xml文件片段。

<project>
  <modelVersion>4.0.0</modelVersion>
        <!-- Content removed for brevity -->

    <scm>
      <connection>scm:git:https://github.com/bava/intro-maven.git</connection>
      <developerConnection>scm:git:https://github.com/bava/intro-maven.git</developerConnection>
      <url>https://github.com/bava/intro-maven</url>
    </scm>
   <!-- Content removed for brevity -->
</project>

Listing 8-3The pom.xml with SCM Information

一旦在本地机器上更新了pom.xml文件,通过运行以下命令将修改后的文件提交给 GitHub:

git commit . -m "Added SCM Information"
git push origin release

为了让 Maven 成功地与 GitHub 通信,它需要 GitHub 凭证。您在settings.xml文件中提供这些信息,如清单 8-4 所示。元素的 ID 被声明为GitHub,因为它必须匹配主机名。

<?xml version="1.0" encoding="UTF-8" ?>
<settings  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

<servers>
   <server>
      <id>nexusReleases</id>
      <username>admin</username>
      <password>admin123</password>
   </server>
   <server>
      <id>nexusSnapshots</id>
      <username>admin</username>
      <password>admin123</password>
   </server>
   <server>
     <id>github</id>
     <username>[your_github_account_name]</username>
     <password>[your_github_account_password]</password>
   </server>
 </servers>
</settings>

Listing 8-4The settings.xml with GitHub Details

现在您已经拥有了 Maven 的prepare目标所需的所有配置。清单 8-5 显示了运行prepare目标的结果。因为prepare目标是在交互模式下运行的,Maven 将提示您发布版本、发布标签和新的开发版本。对于每个提示,按 Enter 键接受 Maven 建议的默认值。

C:\apress\gswm-book\chapter8\gswm>mvn release:prepare
[INFO] Scanning for projects...
[INFO]
[INFO] --------------< com.apress.gswmbook:gswm >--------------
[INFO] Building Getting Started with Maven 1.0.0-SNAPSHOT

[INFO] --- maven-release-plugin:2.5.3:prepare (default-cli) @ gswm ---

[INFO] Verifying that there are no local modifications...

[INFO] Executing: cmd.exe /X /C "git rev-parse --show-toplevel"
[INFO] Working directory: C:\apress\gswm-book\chapter8\gswm
[INFO] Executing: cmd.exe /X /C "git status --porcelain ."

What is the release version for "Getting Started with Maven"? (com.apress.gswmbook:gswm) 1.0.0: :
What is SCM release tag or label for "Getting Started with Maven"? (com.apress.gswmbook:gswm) gswm-1.0.0: :
What is the new development version for "Getting Started with Maven"? (com.apress.gswmbook:gswm) 1.0.1-SNAPSHOT: :

[INFO] Checking in modified POMs...

[INFO] Tagging release with the label gswm-1.0.0...
[INFO] Executing: cmd.exe /X /C "git tag -F C:\Users\bavara\AppData\Local\Temp\maven-scm-73613791.commit gswm-1.0.0"

[INFO] Executing: cmd.exe /X /C "git push https://github.com/bava/intro-maven.git refs/tags/gswm-1.0.0"
[INFO] Release preparation complete.
[INFO] BUILD SUCCESS

Listing 8-5Maven prepare Command

请注意,Git命令作为prepare目标的一部分被执行。成功完成prepare目标将导致 Git 标签的创建,如图 8-12 所示。gswm项目中的pom.xml文件现在将拥有版本 1 . 0 . 1-快照。

img/332298_2_En_8_Fig12_HTML.jpg

图 8-12

在执行prepare时创建的 Git 标签

清扫目标

作为执行的一部分,prepare目标执行许多活动并生成临时文件,如release.propertiespom.xml.releaseBackup。成功完成后,它会清理这些临时文件。有时prepare目标可能会失败(例如,无法连接到 Git)并使项目处于肮脏的状态。这就是发布插件的clean目标出现的地方。顾名思义,它会删除作为发布执行的一部分而生成的任何临时文件。

注意

发布插件的clean目标必须仅在prepare目标失败时使用。

执行目标

perform目标负责从新创建的标签中签出代码,并将发布的代码构建和部署到远程存储库中。

以下阶段是perform目标的一部分:

  • 验证-完成-准备-阶段:这验证了在运行perform目标之前已经执行了一个prepare阶段。

  • check out-project-from-scm:从 SCM 标签中检出发布的代码。

  • 运行-执行-目标:执行与perform相关的目标。默认目标是部署。

gswm项目上运行perform目标的输出如清单 8-6 所示。

C:\apress\gswm-book\chapter8\gswm>mvn release:perform
[INFO] Scanning for projects...

[INFO] -------------< com.apress.gswmbook:gswm >---------------
[INFO] Building Getting Started with Maven 1.0.1-SNAPSHOT
[INFO] --------------------[ jar ]-----------------------------

[INFO] --- maven-release-plugin:2.5.3:perform (default-cli) @ gswm ---
[INFO] Checking out the project to perform the release ...
[INFO] Executing: cmd.exe /X /C "git clone --branch gswm-1.0.0 https://github.com/bava/intro-maven.git C:\apress\gswm-book\chapter8\gswm\target\checkout"

[INFO] Invoking perform goals in directory C:\apress\gswm-book\chapter8\gswm\target\checkout
[INFO] Executing goals 'deploy'...

 [INFO] Building jar: C:\apress\gswm-book\chapter8\gswm\target\checkout\target\gswm-1.0.0-javadoc.jar

 [INFO] --- maven-install-plugin:2.4:install (default-install) @ gswm ---
 [INFO] Installing C:\apress\gswm-book\chapter8\gswm\target\checkout\target\gswm-1.0.0.jar to C:\Users\bavara\.m2\repository\com\apress\gswmbook\gswm\1.0.0\gswm-1.0.0.jar

 [INFO] --- maven-deploy-plugin:2.7:deploy (default-deploy) @ gswm ---
[INFO] Uploading to nexusReleases: http://localhost:8081/repository/maven-releases/com/apress/gswmbook/gswm/1.0.0/gswm-1.0.0.jar

[INFO] Uploaded to nexusReleases: http://localhost:8081/repository/maven-releases/com/apress/gswmbook/gswm/1.0.0/gswm-1.0.0.jar (2.4 kB at 14 kB/s)
[INFO] Uploading to nexusReleases: http://localhost:8081/repository/maven-releases/com/apress/gswmbook/gswm/1.0.0/gswm-1.0.0.pom

[INFO] Uploaded to nexusReleases: http://localhost:8081/repository/maven-releases/com/apress/gswmbook/gswm/1.0.0/gswm-1.0.0-javadoc.jar (22 kB at 84 kB/s)

[INFO] BUILD SUCCESS

Listing 8-6Maven perform Command

这就完成了gswm项目 1.0.0 版本的发布。工件最终出现在 Nexus repository manager 中,如图 8-13 所示。

img/332298_2_En_8_Fig13_HTML.jpg

图 8-13

与发布的工件的关系

摘要

Nexus 等内部存储库管理器允许企业完全采用 Maven。除了充当公共存储库代理之外,它们还支持组件共享和治理。本章介绍了 Maven 与 Nexus 的集成,并向您展示了将工件部署到 Nexus 的过程。您还了解了 Maven 的发布过程及其不同阶段。

在下一章,我们将学习持续集成(CI)的概念,并安装和配置 Jenkins——一个流行的开源 CI 工具。

九、持续集成

持续集成(CI)是一种软件开发最佳实践,开发人员每天数次将对他们代码的更改集成到一个公共存储库中。每一个提交的变更都会导致一个自动构建,这个自动构建会编译代码,运行测试,并生成工件的一个新版本。构建过程中的任何错误都将立即报告给开发团队。这种频繁的代码集成允许开发人员在开发周期的早期发现并解决集成问题。

图 9-1 显示了持续集成以及相关组件的可视化表示。CI 流程从开发人员将她的变更提交给诸如 Git 或 SVN 之类的源代码控制系统开始。CI 服务器会收到通知或观察/查询新的代码变更,一旦发现变更,就会检查源代码并开始构建过程。在成功的构建中,CI 服务器可以将工件发布到存储库或测试服务器。作为最后一步,关于构建状态的通知被发送给开发团队。

img/332298_2_En_9_Fig1_HTML.jpg

图 9-1

CI 组件

Jenkins 是一个流行的开源 CI 服务器,它与 Maven 集成得很好。其他流行的 CI 服务器包括 Bamboo、TeamCity 和 GitLab。在这一章中,我们将安装并配置 Jenkins 来触发基于 Maven 的项目的自动构建。

安装 Jenkins

Jenkins 以几种方式发布——本地安装程序、Docker 容器和可执行的 WAR 文件。在本书中,我们将使用长期支持(LTS)的可执行 WAR 文件版本,您可以在 https://jenkins.io/download/ 下载。将下载的版本保存在 c:\tools\jenkins。

下载完成后,使用命令行导航到下载的文件夹并运行命令:Java–jar Jenkins . war成功执行命令后,打开浏览器并导航至http://localhost:8080。系统将提示您从“initialAdminPassword”文件中找到并输入自动生成的管理员密码。在下一个屏幕上,选择“安装建议的插件”并等待安装程序完成插件安装。在“创建第一个管理员用户”屏幕上,输入“Admin”作为用户名,输入“admin123”作为密码,并填写表格上的其余详细信息。完成 Jenkin 的配置后,您应该会看到类似于图 9-2 的 Jenkins 仪表盘。

img/332298_2_En_9_Fig2_HTML.png

图 9-2

詹金斯仪表板

Maven 项目

为了理解 Jenkins 对 Maven 的支持,我们需要一个源代码控制服务器上的示例 Maven 项目。在本章中,我们将使用位于 https://github.com/bava/gswm-jenkins 的 GitHub 上的 gwsm-jenkins 项目。为了让您理解本章的其余部分,您需要将 gswm-jenkins 存储库放在您自己的帐户下。你可以登录 GitHub,点击如图 9-3 所示的分叉按钮。

img/332298_2_En_9_Fig3_HTML.jpg

图 9-3

Fork gswm-jenkins 知识库

配置 Jenkins

要开始 Jenkins 配置,请单击仪表板上的“新项目”链接。在新项目屏幕上,选择自由式项目并输入名称“gswm-jenkins-integration”,如图 9-4 所示。

img/332298_2_En_9_Fig4_HTML.jpg

图 9-4

新项目屏幕

在下一个屏幕上,在 General 部分,选择“GitHub project”复选框并输入项目 URL。这应该是您 GitHub 帐户上分叉项目位置的 URL。

img/332298_2_En_9_Fig5_HTML.png

图 9-5

新项目-常规部分

在“源代码管理”部分,选择“Git”单选按钮并输入 GitHub 库的 URL,如图 9-6 所示。这是 GitHub 克隆 URL,您可以通过点击存储库名称下的“克隆或下载”找到它。

img/332298_2_En_9_Fig6_HTML.jpg

图 9-6

新项目源代码管理部分

为了让 Jenkins 检查您的代码,您需要提供您的 GitHub 凭据。您可以点击凭证旁边的“添加”按钮,输入您的用户名和密码,如图 9-7 所示。

img/332298_2_En_9_Fig7_HTML.png

图 9-7

GitHub 凭证输入

在“构建触发器”部分,选择“轮询 SCM”选项,并输入“H/15∑∑∑”作为值,如图 9-8 所示。这表明 Jenkins 需要每 15 分钟轮询一次 GitHub repo 的变化。

img/332298_2_En_9_Fig8_HTML.png

图 9-8

构建触发器轮询计划

在“构建”部分,点击“添加构建步骤”并选择“调用顶级 Maven 目标”。输入“全新安装”作为目标值,如图 9-9 所示。

img/332298_2_En_9_Fig9_HTML.png

图 9-9

Maven 的构建步骤

最后,在 Post-build Actions 部分,点击“Add post-build action”并选择“Archive the artifacts”。输入∫∫/∫。jar 作为要归档文件的值,如图 9-10 所示。

img/332298_2_En_9_Fig10_HTML.jpg

图 9-10

存档工件部分

再次单击“添加构建后操作”按钮,并选择“发布 JUnit 测试结果报告”。输入“target/surefire-reports/*。xml "作为测试报告的 XMLs 值如图 9-11 所示。单击保存保存配置。

img/332298_2_En_9_Fig11_HTML.jpg

图 9-11

发布 JUnit 结果

触发构建作业

我们现在已经做好了让 Jenkins 构建我们项目的一切准备。在“项目作业”页面上,单击“立即构建”链接以触发新的构建。这将启动一个带有数字编号的新构建,您可以从页面左下角的构建历史部分访问该数字编号。单击内部版本号旁边的下拉箭头,并选择“控制台输出”。这将把你带到类似图 9-12 的输出屏幕。

img/332298_2_En_9_Fig12_HTML.jpg

图 9-12

作业控制台输出屏幕

成功完成工作后,您将在项目页面上看到构建的工件,如图 9-13 所示。

img/332298_2_En_9_Fig13_HTML.jpg

图 9-13

Jenkins 项目页面-构建工件

运行的测试结果也可以在项目页面的“最新测试结果”下找到。

摘要

在这一章中,你学习了持续集成和配置 Jenkins 与 Maven 项目交互。

这场讨论将我们带到旅程的终点。在整本书中,你已经学习了 Maven 背后的关键概念。我们希望您将使用您新发现的 Maven 知识来自动化和改进您现有的构建和软件开发过程。

posted @ 2024-08-06 16:40  绝不原创的飞龙  阅读(29)  评论(0编辑  收藏  举报