首页 » Netty实战 » Netty实战全文在线阅读

《Netty实战》附录 Maven介绍

关灯直达底部

本附录提供了对Apache Maven(http://maven.apache.org/what-is-maven.html)的基本介绍。在读过之后,你应该能够通过复用本书示例中的配置来启动你自己的项目。

Maven是一个强大的工具,学习的回报很大。如果希望了解更多,你可以在http://maven. apache.org找到官方文档,在www.sonatype.com/resources/books找到一套极好的免费的PDF格式的书。

第一节将介绍Maven的基本概念。在第二节中,我们将使用本书示例项目中的示例来说明这些基本概念。

A.1 什么是Maven

Maven是一种用来管理Java项目的工具,但不是那种用来管理资源规划和调度的工具。相反,它处理的是管理一个具体的项目所涉及的各种任务,如编译、测试、打包、文档以及分发。

Maven包括以下的几个部分。

  • 一组用于处理依赖管理、目录结构以及构建工作流的约定。基于这些约定实现的标准化可以极大地简化开发过程。例如,一个常用的目录结构使得开发者可以更加容易地跟上不熟悉的项目的节奏。
  • 一个用于项目配置的XML Schema:项目对象模型(Project Object Model),简称POM[1]。每一个Maven项目都拥有一个POM文件[2],默认命名为pom.xml,包含了Maven用于管理该项目的所有的配置信息。
  • 一个委托外部组件来执行项目任务的插件架构。这简化了更新以及扩展Maven能力的过程。

构建和测试我们的示例项目只需要用到Maven多种特性的一个子集。这些也是我们将在本附录中所讨论的内容,其中不包括那些在生产部署中肯定需要用到的特性。我们将会涵盖的主题包括以下内容。

  • 基本概念:构件、坐标以及依赖。
  • 关键元素以及Maven项目描述符(pom.xml)的用法。
  • Maven构建的生命周期以及插件。

A.1.1 安装和配置Maven

可以从http://maven.apache.org/download.cgi下载适合于你的系统的Maven tar.gz或者zip文件。安装非常简单:将该归档内容解压到你选择的任意文件夹(我们称之为<安装目录>)中。这将创建目录<安装目录>/apache-maven-3.3.9[3]。

然后,

  • 将环境变量M2_HOME设置为指向<安装目录>/apache-maven-3.3.9,这个环境变量将会告诉Maven在哪里能找到它的配置文件,conf/settings.xml
  • %M2_HOME%/bin(在Linux上是${M2_HOME}/bin)添加到你的执行路径,在这之后,在命令行执行mvn就能运行Maven了。

在编译和运行示例项目时,不需要修改默认配置。在首次执行mvn时,Maven会为你创建本地存储库[4],并从Maven中央存储库下载基本操作所需的大量JAR文件。最后,它会下载构建当前项目所需要的依赖项(包括Netty的JAR包)。关于自定义settings.xml的详细信息可以在http://maven.apache.org/settings.html找到。

A.1.2 Maven的基本概念

在下面的章节中,我们将解释Maven的几个最重要的概念。熟悉这些概念将有助于你理解POM文件的各个主要元素。

1.标准的目录结构

Maven定义了一个标准的项目目录结构[5]。并不是每种类型的项目都需要Maven的所有元素,很多都可以在必要的时候在POM文件中重写。表A-1展示了一个基本的WAR项目,有别于JAR项目,它拥有src/main/webapp文件夹。当Maven构建该项目时,该目录(其中包含WEB-INF目录)的内容将会被放置在WAR文件的根路径上。位于该文件树根部的${project.basedir}是一个标准的Maven属性,标识了当前项目的根目录。

表A-1 基本的项目目录结构

文 件 夹

描  述

/${project.basedir}

项目根路径

|---/src

源代码根路径

   |---/main

程序代码

      |---/java

Java源代码

      |---/resources

属性文件、XML schema等

      |---/webapp

Web应用程序资源

    |---/test

测试源代码根路径

       |---/java

Java源代码,如JUnit测试类

       |---/resources

属性文件、XML schema等

|---/target

由构建过程所创建的文件

2.POM大纲

代码清单A-1是我们的一个示例项目的POM文件的大纲。只显示了顶层的schema元素。其中的一些也是其他元素的容器。

代码清单A-1 POM文件的大纲

<project>  ← --  根元素  <groupId/>   <artifactId/>  ← --  唯一地定义一个Maven 项目的值  <version/>   <packaging/>  ← --   该项目所产生的构件的类型;默认值是jar  <properties/>  ← -- 在POM 中所引用的符号  <dependencies/>  ← -- 构建当前项目所需要的其他Maven 项目    <build/>  ← -- 构建该项目所需要执行的任务的配置    <profiles/>  ← -- 为不同的用例自定义POM的命名的配置  </project>  

我们将在本节剩下的部分中更加详细地讨论这些元素。

3.构件

任何可以被Maven的坐标系统(参见接下来的关于GAV坐标的讨论)唯一标识的对象都是一个Maven构件。大多数情况下,构件是构建Maven项目所生成的文件,如JAR。但是,只包含其他POM(该文件本身并不产生构件)使用的定义的POM文件也是Maven构件。

Maven构件的类型由其POM文件的<packaging>元素指定。最常用的值是pomjarearwar以及maven-plugin

4.POM文件的用例

可以通过以下的方式来使用POM文件。

  • 默认的——用于构建一个构件。
  • 父POM——提供一个由子项目继承的单个配置信息源——声明这个POM文件作为它们的<parent>元素的值。
  • 聚合器——用于构建一组声明为<modules>的项目,这些子项目位于其当前聚合器项目的文件夹中,每个都包含有它自己的POM文件。

作为父POM或者聚合器的POM文件的<packaging>元素的值将是pom。注意,一个POM文件可能同时提供两项功能。

5.GAV坐标

POM定义了5种称为坐标的元素,用于标识Maven构件。首字母缩写GAV指的是必须始终指定的3个坐标<groupId><artifactId>以及<version>的首字母。

下面的坐标是按照它们在坐标表达式中出现的顺序列出的。

(1)<groupId>是项目或者项目组的全局的唯一标识符。这通常是Java源代码中使用的全限定的Java包名。例如,io.netty、com.google。

(2)<artifactId>用于标识和某个<groupId>相关的不同的构件。例如,netty-allnetty-handler

(3)<type>是指和项目相关的主要构件的类型(对应于构件的POM文件中的<packaging>值)。它的默认值是jar。例如,pomwarear

(4)<version>标识了构件的版本。例如,1.1、2.0-SNAPSHOT[6]、4.1.9.Final。

(5)<classifier>用于区分属于相同的POM但是却被以不同的方式构建的构件。例如,javadoc、sources、jdk16、jdk17。

一个完整的坐标表达式具有如下格式:

artifactId:groupId:packaging:version:classifier  

下面的GAV坐标标识了包含所有Netty组件的JAR:

io.netty:netty-all:4.1.9.Final  

POM文件必须声明它所管理的构件的坐标。一个具有如下坐标的项目:

<groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.9.Final</version><packaging>jar</packaging>  

将会产生一个具有以下格式的名称的构件:

<artifactId>-<version>.<packaging>  

在这种情况下,它将产生这个构件:

netty-all-4.1.9.Final.jar  

6.依赖

项目的依赖是指编译和执行它所需要的外部构件。在大多数情况下,你的项目的依赖项也会有它自己的依赖。我们称这些依赖为你的项目的传递依赖。一个复杂的项目可能会有一个深层级的依赖树;Maven提供了各种用于帮助理解和管理它的工具。[7]

Maven的<dependency>[8]声明在POM的<dependencies>元素中:

<dependencies>  <dependency>    <groupId/>    <artifactId/>    <version/>    <type/>    <scope/>    <systemPath/>  </dependency>  ...</dependencies>  

<dependency>声明中,GAV坐标总是必不可少的[9]。type以及scope元素对于那些值不分别是默认值jarcompile的依赖来说也是必需的。

下面的代码示例是从我们示例项目的顶级POM中摘录的。注意第一个条目,它声明了对我们先前提到的Netty JAR的依赖。

<dependencies>  <dependency>    <groupId>io.netty<groupId>    <artifactId>netty-all</artifactId>     <version>4.1.9.Final</version>  </dependency>  <dependency>    <groupId>nia</groupId>    <artifactId>util</artifactId>    <version>1.0-SNAPSHOT</version>  </dependency>  <dependency>    <groupId>com.google.protobuf</groupId>    <artifactId>protobuf-java</artifactId>    <version>2.5.0</version>  </dependency>  <dependency>    <groupId>org.eclipse.jetty.npn</groupId>    <artifactId>npn-api</artifactId>=    <version>1.1.0.v20120525</version>  </dependency>  <dependency>    <groupId>junit</groupId>    <artifactId>junit</artifactId>    <version>4.11</version>    <scope>test</scope>  </dependency></dependencies>  

<scope>元素可以具有以下值。

  • compile——编译和执行需要的(默认值)。
  • runtime——只有执行需要。
  • optional——不被引用了这个项目所产生的构件的其他项目,视为传递依赖。
  • provided——不会被包含在由这个POM产生的WAR文件的WEB_INF/lib目录中。
  • test——只有编译和测试的执行需要。
  • import——这将在后面的“依赖管理”一节进行讨论。

<systemPath>元素用来指定文件系统中的绝对位置。

Maven用来管理项目依赖的方式,包括了一个用来存储和获取这些依赖的存储库协议,已经彻底地改变了在项目之间共享JAR文件的方式,从而有效地消除了项目的中每个开发人员都维护一个私有lib目录时经常会出现的问题。

7.依赖管理

POM的<dependencyManagement>元素包含可以被其他项目使用的<dependency>声明。这样的POM的子项目将会自动继承这些声明。其他项目可以通过使用<scope>元素的import值来导入它们(将在稍后讨论)。

引用了<dependencyManagement>元素的项目可以使用它所声明的依赖,而不需要指定它们的<version>坐标。如果<dependencyManagement>中的<version>在稍后有所改变,则它将被所有引用它的POM拾起。

在下面的示例中,所使用的Netty版本是在POM的<properties>部分中定义,在<dependencyManagement>中引用的。

<properties>  <netty.version>4.1.9</netty.version>  ...  ...</properties><dependencyManagement>  <dependencies>    <dependency>      <groupId>io.netty</groupId>      <artifactId>netty-all</artifactId>      <version>${netty.version}</version>    </dependency>  </dependencies>  ...</dependencyManagement>  

对于这种使用场景,依赖的<scope>元素有一个特殊的import值:它将把外部POM(没有被声明为<parent>)的<dependencyManagement>元素的内容导入到当前POM的<dependency Management>元素中。

8.构建的生命周期

Maven构建的生命周期是一个明确定义的用于构建和分发构件的过程。有3个内置的构建生命周期:cleandefaultsite。我们将只讨论其中的前两个,分别用于清理和分发项目。

一个构建的生命周期由一系列的阶段所组成。下面是默认的构建生命周期的各个阶段的一个部分清单。

  • validate——检查项目是否正确,所有必需的信息是否已经就绪。
  • process-sources——处理源代码,如过滤任何值。
  • compile——编译项目的源代码。
  • process-test-resources——复制并处理资源到测试目标目录中。
  • test-compile——将测试源代码编译到测试目标目录中。
  • test——使用合适的单元测试框架测试编译的源代码。
  • package——将编译的代码打包为它的可分发格式,如JAR。
  • integration-test——处理并将软件包部署到一个可以运行集成测试的环境中。
  • verify——运行任何的检查以验证软件包是否有效,并且符合质量标准。
  • install——将软件包安装到本地存储库中,在那里其他本地构建项目可以将它引用为依赖。
  • deploy——将最终的构件上传到远程存储库,以与其他开发人员和项目共享。

执行这些阶段中的一个阶段将会调用所有前面的阶段。例如:

mvn package  

将会执行validatecompile以及test,并随后将该构件组装到该项目的目标目录中。

执行

mvn clean install  

将会首先移除所有先前的构建所创建的结果。然后,它将会运行所有到该阶段的默认阶段,并且包括将该构件放置到你的本地存储库的文件系统中。

虽然我们的示例项目可以通过这些简单的命令来构建,但是任何使用Maven的重要工作都需要详细了解构建生命周期的各个阶段。[10]

9.插件

虽然Maven协调了所有构建生命周期阶段的执行,但是它并没有直接实现它们,相反,它将它们委托给了插件[11]**,这些插件是maven-plugin类型的构件(打包为JAR文件)。Apache Maven项目为标准构建生命周期所定义的所有任务都提供了插件,更多的是由第三方生产的,用于处理各种自定义的任务。

插件可能拥有多个内部步骤,或者目标,其也可以被单独调用。例如,在一个JAR项目中,默认的构建生命周期由maven-jar-plugin处理,其将构建的各个阶段映射到了它自己的以及其他插件的目标中,如表A-2所示。

表A-2 阶段、插件以及目标

阶  段

插件:目标

process-resources

resources:resources

compile

compiler:compiler

process-test-resources

resources:testResources

test-compile

compiler:testCompile

test

surefire:test

package

jar:jar

install

install:install

deploy

deploy:deploy

在我们的示例项目中,我们使用了下面的第三方插件来从命令行执行我们的项目。注意插件的声明,它被打包为JAR包,使用了和<dependency>的GAV坐标相同的GAV坐标。

<plugin>  <groupId>org.codehaus.mojo</groupId>  <artifactId>exec-maven-plugin</artifactId>  <version>1.2.1</version></plugin>  

10.插件管理

如同<dependencyManagement><pluginManagement>声明了其他POM可以使用的信息,如代码清单A-2所示。但是这只适用于子POM,因为对于插件来说,没有导入声明。和依赖一样,<version>坐标是继承的。

代码清单A-2 pluginManagement

<build>  <pluginManagement>    <plugins>      <plugin>        <artifactId>maven-compiler-plugin</artifactId>        <version>3.2</version>        <configuration>          <source>1.7</source>          <target>1.7</target>        </configuration>      </plugin>      <plugin>        <groupId>org.codehaus.mojo</groupId>        <artifactId>exec-maven-plugin</artifactId>        <version>1.2.1</version>      </plugin>    </plugins>  </pluginManagement></build> 

代码清单A-3展示了代码清单A-2中的POM片段的子POM是如何使用其父POM的<pluginManagement>配置的,它只引用了其构建所需的插件。子POM还可以重写它需要自定义的任何插件配置。

关于Maven插件

在声明由Maven项目生成的插件时,可以省略groupId(org.apache.maven.plugins),如代码清单A-2中的maven-compiler-plugin的声明中所示。此外,保留了以“maven”开头的artifactId,仅供Maven项目使用。例如,第三方可以提供一个artifactIdexec-maven-plugin的插件,但是不能为maven-exec-plugin

POM定义了一个大多数插件都需要遵从的插件配置格式。

更多的信息参见Maven的“插件配置指南”(http://maven.apache.org/guides/mini/guide-configuring- plugins.html)。这将帮助你设置你想要在自己的项目中使用的任何插件。

代码清单A-3 插件继承

<build>  <plugins>    <plugin>      <artifactId>maven-compiler-plugin</artifactId>    </plugin>    <plugin>      <groupId>org.codehaus.mojo</groupId>      <artifactId>exec-maven-plugin</artifactId>    </plugin>  </plugins></build>  

11.配置文件

配置文件(在<profiles>中定义)是一组自定义的POM元素,可以通过自动或者手动启用(激活)来改变POM的行为。例如,你可以定义一个配置文件,它将根据JDK版本、操作系统或者目标部署环境(如开发、测试或者生产环境)来设置构建参数。

可以通过命令行的-P标志来显式地引用配置文件。下面的例子将激活一个将POM自定义为使用JDK1.6的配置文件。

mvn -P jdk16 clean install  

12.存储库

Maven的构件存储库[12]可能是远程的,也可能是本地的。

  • 远程存储库是一个Maven从其下载POM文件中所引用的依赖的服务。如果你有上传权限,那么这些依赖中可能也会包含由你自己的项目所产生的构件。大量开放源代码的Maven项目(包含Netty)都将它们的构件发布到可以公开访问的Maven存储库。
  • 本地存储库是一个本地的目录,其包含从远程存储库下载的构件,以及你在本地机器上构建并安装的构件。它通常放在你的主目录下,如:
  C:/Users/maw/.m2/repository  

Maven存储库的物理目录结构使用GAV坐标,如同Java编译器使用包名一样。例如,在Maven下载了下面的依赖之后:

<dependency>  <groupId>io.netty</groupId>  <artifactId>netty-all</artifactId>  <version>4.1.9.Final</version></dependency>  

将会在本地存储库中找到以下内容:

.m2/repository|---/io  |---/netty    |---/netty-all      |---/4.1.9.Final          netty-all-4.1.9.Final.jar          netty-all-4.1.9.Final.jar.sha1          netty-all-4.1.9.Final.pom          netty-all-4.1.9.Final.pom.sha1          _maven.repositories  

13.快照和发布

远程存储库通常会为正在开发的构件,以及那些稳定发布或者生产发布的构件,定义不同的区域。这些区域被分别称为快照存储库和发布存储库。

一个<version>值由-SNAPSHOT结尾的构件将被认为是还没有发布的。这种构件可以重复地使用相同的<version>值被上传到存储库。每次它都会被分配一个唯一的时间戳。当项目检索构件时,下载的是最新实例。

一个<version>值不具有-SNAPSHOT后缀的构件将会被认为是一个发布版本。通常,存储库策略只允某一特定的发布版本上传一次。

当构建一个具有SNAPSHOT依赖的项目时,Maven将检查本地存储库中是否有对应的副本。如果没有,它将尝试从指定的远程存储库中检索,在这种情况下,它将接收到具有最新时间戳的构件。如果本地的确有这个构件,并且当前构建也是这一天中的第一个,那么Maven将默认尝试更新该本地副本。这个行为可以通过使用Maven配置文件(settings.xml)中的配置或者命令行标志来进行配置。

A.2 POM示例

在这一节中,我们将通过介绍一些POM示例来说明我们在前一节中所讨论的主题。

A.2.1 一个项目的POM

代码清单A-4展示了一个POM,其为一个简单的Netty项目创建了一个JAR文件。

代码清单A-4 独立的pom.xml

<?xml version="1.0" encoding="ISO-8859-15"?><project xmlns="http://maven.apache.org/POM/4.0.0"  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>   ← --  该项目的GAV 坐标  <groupId>com.example</groupId>    <artifactId>myproject</artifactId>  <version>1.0-SNAPSHOT</version>  <packaging>jar</packaging>  ← -- 该项目产生的构件将是一个JAR文件(默认值)  <name>My Jar Project</name>  <dependencies>    <dependency>  ← -- 这个POM 只声明了Netty JAR作为依赖;一个典型的Maven项目会有许多依赖       <groupId>io.netty</groupId>      <artifactId>netty-all</artifactId>      <version>4.1.9.Final</version>    </dependency>  </dependencies>  <build>  ← -- <build>部分声明了用于执行构建任务的插件。我们只自定义了编译器插件,对于其他的插件,我们接受默认值    <plugins>      <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-compiler-plugin</artifactId>        <version>3.2</version>        <configuration>          <source>1.7</source>          <target>1.7</target>        </configuration>      </plugin>    </plugins>  </build></project>  

这个POM创建的构件将是一个JAR文件,其中包含从项目的Java源代码编译而来的类。在编译的过程中,被声明为依赖的Netty JAR将会被添加到CLASSPATH中。

下面是使用这个POM时会用到的基本Maven命令。

  • 在项目的构建目录(“target”)中创建JAR文件:
  mvn package  
  • 将该JAR文件存储到本地存储库中:
  mvn install  
  • 将该JAR文件发布到全局存储库中(如果已经定义了一个):
  mvn deploy  

A.2.2 POM的继承和聚合

正如我们之前所提到的,有几种使用POM的方式。在这里,我们将讨论它作为父POM或者聚合器的用法。

1.POM继承

POM文件可能包含子项目要继承(并可能重写)的信息。

2.POM聚合

聚合器POM会构建一个或者多个子项目,这些子项目驻留在该POM所在目录的子目录中。子项目,或者<modules>标签,是由它们的目录名标识的:

<modules>  <module>Server</module>  <module>Client</module></modules>  

当构建子项目时,Maven将创建一个reactor,它将计算存在于它们之间的任何依赖,以确定它们必须遵照的构建顺序。注意,聚合器POM不一定是它声明为模块的项目的父POM。(每个子项目都可以声明一个不同POM作为它的<parent>元素的值。)

用于第2章的Echo客户端/服务器项目的POM既是一个父POM,也是一个聚合器[13]。示例代码根目录下的chapter2目录,包含了代码清单A-5中所展示的内容。

代码清单A-5 chapter2目录树

chapter2  |---pom.xml    ← --  父级/聚合器POM  |---/Client  ← -- 客户端模块    |---pom.xml    |---/src      |---/main        |---/java          |---/nia            |---/chapter2              |---/echoclient                EchoClient.java                EchoClientHandler.java  |---/Server  ← --  服务器模块    |---pom.xml    |---/src      |---/main        |---/java          |---/nia            |---/chapter2              |---/echoserver                EchoServer.java                EchoServerHandler.java  

代码清单A-6所示的根级POM的打包类型是<pom>,这表示它本身并不产生构件。相反,它会为将它声明为<parent>的项目提供配置信息,如该Client和Server项目。它也是一个聚合器,这意味着你可以通过在chapter2目录中运行mvn install来构建它的<modules>中所定义的模块。

代码清单A-6 父级和聚合器POM:echo-parent

<project>  <modelVersion>4.0.0</modelVersion>  <parent>  ← --  <parent>声明了samples-parentPOM 作为这个POM 的父POM    <groupId>nia</groupId>    <artifactId>nia-samples-parent</artifactId>    <version>1.0-SNAPSHOT</version>  </parent>  <artifactId>chapter2</artifactId>  <packaging>pom</packaging>   <name>2. Echo Client and Server</name>  <modules> ← --  <modules>声明了父POM 下的目录,其中包含将由这个POM 来构建的Maven 项目     <module>Client</module>    <module>Server</module>  </modules>  <properties>  ← -- <property>值可以通过在命令行上使用Java 系统属性(-D)进行重写。属性由子项目继承     <echo-server.hostname>localhost</echo-server.hostname>    <echo-server.port>9999</echo-server.port>  </properties>   <dependencies>  ← -- 父POM 的<dependencies>元素由子项目继承     <dependency>      <groupId>io.netty</groupId>      <artifactId>netty-all</artifactId>    </dependency>  </dependencies>  <build>    <plugins>  ← -- 父POM 的<plugins>元素由子项目继承        <plugin>        <artifactId>maven-compiler-plugin</artifactId>      </plugin>      <plugin>        <artifactId>maven-failsafe-plugin</artifactId>      </plugin>      <plugin>        <artifactId>maven-surefire-plugin</artifactId>      </plugin>      <plugin>        <groupId>org.codehaus.mojo</groupId>        <artifactId>exec-maven-plugin</artifactId>      </plugin>    </plugins>  </build></project>  

得益于Maven对于继承的支持,该Server和Client项目的POM并没有太多的事情要做。代码清单A-7展示了该Server项目的POM。(该Client项目的POM几乎是完全相同的。)

代码清单A-7 Echo-服务器项目的POM

<project>  ← --  <parent>声明了父POM  <parent>    <groupId>nia</groupId>     <artifactId>chapter2</artifactId>    <version>1.0-SNAPSHOT</version>  </parent>  <artifactId>echo-server</artifactId>   ← --  <artifactId>必须声明,因为对于该子项目来说它是唯一的。<groupId>和<version>,如果没有被定义则从父POM 继承  <build>    <plugins>    ← --  exec-maven-plugin 插件可以执行Maven 命令行的任意命令;在这里,我们用它来运行Echo 服务器      <plugin>        <groupId>org.codehaus.mojo</groupId>        <artifactId>exec-maven-plugin</artifactId>        <executions>          <execution>            <id>run-server</id>            <goals>              <goal>java</goal>            </goals>          </execution>        </executions>        <configuration>           <mainClass>nia.echo.EchoServer</mainClass>            <arguments>            <argument>${echo-server.port}</argument>          </arguments>        </configuration>      </plugin>    </plugins>  </build></project>  

这个POM非常简短,因为它从它的父POM和祖父POM(甚至还有一个曾祖父级别的POM存在——Maven Super POM)那里继承了非常多的信息。注意,例如,${echo-server.port}属性的使用,其继承自父POM。

Maven执行的POM,在组装了所有的继承信息并应用了所有的活动配置文件之后,被称为“有效POM”。要查看它,请在任何POM文件所在的目录中执行下面的Maven命令:

mvn help:effective-pom  

A.3 Maven命令行

mvn命令的语法如下:

mvn [options] [<goal(s)>] [<phase(s)>]  

有关其用法的详细信息,以及有关我们在这个附录中所讨论的许多主题的更多信息,参见Sonatype的《Maven: The Complete Reference》,这是一个很好的资源。[14]

表A-3展示了mvn的命令行选项,这些选项可以通过执行。

mvn –help  

来显示。

表A-3 mvn的命令行参数

选  项

描  述

-am,--also-make

如果指定了项目列表,还会构建列表所需的项目

-amd,--also-make-dependents

如果指定了项目列表,还会构建依赖于列表中的项目的项目

-B,--batch-mode

在非交互(批处理)模式下运行

-b,--builder <arg>

要使用的构建策略的id

-C,--strict-checksums

如果校验和不匹配,则让这次构建失败

-c,--lax-checksums

如果校验和不匹配,则发出警告

-cpu,--check-plugin-updates

无效,只是为了保持向后的兼容性

-D,--define <arg>

定义一个系统属性

-e,--errors

生成执行错误的信息

-emp,--encrypt-master-password <arg>

加密主安全密码

-ep,--encrypt-password <arg>

加密服务器密码

-f,--file <arg>

强制使用备用的POM文件(或者包含pom.xml的目录)

-fae,--fail-at-end

只在最后让构建失败,允许所有不受影响的构建继续进行

-ff,--fail-fast

在反应化的构建中,首次失败便停止构建

-fn,--fail-never

不管项目的结果如何,都决不让构建失败

-gs,--global-settings <arg>

全局设置文件的备用路径

-h,--help

显示帮助信息

-l,--log-file <arg>

所有构建输出的日志文件的位置

-llr,--legacy-local-repository

使用Maven2的遗留本地存储库(Legacy Local Repository)行为;也就是说,不使用_remote.repositories。也可以通过使用-Dmaven.legacyLocalRepo=true.激活

-N,--non-recursive

不递归到子项目中

-npr,--no-plugin-registry

无效,只是为了保持向后的兼容性

-npu,--no-plugin-updates

无效,只是为了保持向后的兼容性

-nsu,--no-snapshot-updates

取消快照更新

-o,--offline

脱机工作

-P,--activate-profiles <arg>

等待被激活的由逗号分隔的配置文件列表

-pl,--projects <arg>

构建由逗号分隔的指定的reactor项目,而不是所有项目。 项目可以通过[groupId]:artifactId或者它的相对路径来指定

-q,--quiet

静默输出,只显示错误

-rf,--resume-from <arg>

从指定的项目恢复reactor

-s,--settings <arg>

用户配置文件的备用路径

-T,--threads <arg>

线程数目,如2.0C,其中C是乘上的CPU核心数

-t,--toolchains <arg>

用户工具链文件的备用路径

-U,--update-snapshots

强制检查缺少的发布,并更新远程存储库上的快照

-up,--update-plugins

无效,只是为了保持向后的兼容性

-V,--show-version

显示版本信息而不停止构建

-v,--version

显示版本信息

--debug

生成执行调试输出

A.4 小结

在本附录中,我们介绍了Apache Maven,涵盖了它的基本概念和主要的用例。我们通过本书示例项目中的例子说明了这一切。

我们目标是帮助你更好地理解这些项目的构建方式,并为独立开发提供了一个起点。


[1] Maven项目,“What is a POM?”:http://maven.apache.org/guides/introduction/introduction-tothe-pom.html。

[2] 在http://maven.apache.org/ref/3.3.9/maven-model/maven.html有关于POM的详细描述。

[3] 在本书中文版出版时,Maven的最新版本是3.3.9。

[4] 在默认情况下,这是你当前操作系统的HOME目录下的.m2/repository目录。

[5] 有关标准目录结构的优点,参考http://maven.apache.org/guides/introduction/introductionto-the-standard- directory-layout.html。

[6] 有关SNAPSHOT构件的更多信息参见本节后面关于“快照和发布”的讨论。

[7] 例如,在拥有POM文件的项目目录中,在命令行执行“mvn dependency:tree”。

[8] 管理依赖项:http://maven.apache.org/guides/introduction/introduction-to-dependencymechanism.html。

[9] 参见后面的“依赖管理”小节。

[10] “Introduction to the Build Lifecycle”:http://maven.apache.org/guides/introduction/introduction-to-thelifecycle.html。

[11] “Available Plugins”:http://maven.apache.org/plugins/index.html。

[12] 参考http://maven.apache.org/guides/introduction/introduction-to-repositories.html。

[13] 它也是它的上级目录中的nia-samples-parent POM的一个子POM,继承了其元素的值,并传递给了它自己的子项目。

[14] 参见http://books.sonatype.com/mvnref-book/pdf/mvnref-pdf.pdf。