Maven 2.0:编译、测试、部署、运行

 
mycj 发表于 2006-06-12 08:45:30
作者 :Chris Hardin;mycj     来源 :matrix;onjava
评论数 :6 点击数 :1,708     投票总得分 :23 投票总人次 :7
关键字 :Maven2

摘要:

Maven1.0 已经历了几年的时间,并且作为 Ant 的替代品已被广大的开发人员所接收,但它并没有在很大程度使开发人员从 Ant build.xml 文件中解脱出来。 Maven1.0 速度慢并且笨拙,使用起来的困难度并不亚于使用 Ant 的项目。事实上,它的核心是基于 Ant 实现的。在经过了几乎彻底的重写后, Maven2.0 诞生了。
工具箱
一个 Java 项目中最困难的地方就是如何着手启动它。在启动项目之前,我们必须配置好所有的逻辑关系。比如, Java 源代码应该放在何处?单元测试应该在何处进行?依赖的 jar 包应该如何放置?如何构建项目,如何形成文档,如何测试和部署项目?在这种情况下,开发人员不同的处理选择将会影响项目的余下部分。您的选择可能会使你陷入困境,也可能会在将来证明您是一位 Java 架构大师。我们假定后者是我们奋斗的目标,接下来就进入我们的正题。

构建一个 Java 项目可以使用很多工具,其中包括 Ant Ant 作为一款具有革命性的工具,一直是众多开发者使用工具中的首选,它能使开发人员摆脱使用大量 make 命令的苦海。对于那些不太熟悉 make 命令的人来说,他们有充足的理由来表明使用命令并不是构建 Java 项目的最好工具,因为它不具备平台独立性并且不易使用。 Ant 的出现解决了以上的问题,它使用了一个平台独立的工具,该工具能够解析 XML 配置文件,即 build.xml 。虽然 Ant 由于其诸多的优点而备受欢迎,但它同样有一些缺点。 build.xml 文件由于采用了极其简短的描述方式,使得开发人员需要预先学习它的语法。虽然学习曲线不是很陡峭,但 Java 开发人员更应该把时间放在开发上面。

Maven
是新一代的生力军,它的境遇正好和几年前的 Ant 十分类似。 Maven1.0 已经历了几年的时间,并且作为 Ant 的替代品已被广大的开发人员所接收,但它并没有在很大程度使开发人员从 Ant build.xml 文件中解脱出来。 Maven1.0 速度慢并且笨拙,使用起来的困难度并不亚于使用 Ant 的项目。事实上,它的核心是基于 Ant 实现的。在经过了几乎彻底的重写后, Maven2.0 诞生了。

版权声明:任何获得 Matrix 授权的网站,转载时请务必保留以下作者信息和链接
作者 :Chris Hardin;mycj( 作者的 blog:http://blog.matrix.org.cn/page/mycj)
原文 :http://www.onjava.com/pub/a/onjava/2006/03/29/maven-2-0.html
Matrix:http://www.matrix.org.cn/resource/article/44/44475_Maven2.html
关键字 :Maven2

Maven2.0 的优点

Maven2.0
有许多很好功能,这些功能不仅仅是帮助您构建项目。如果您刚刚开始启动一个 Java 项目,并且想使该项目快速地开展下去, Maven2.0 能够在几分钟内达到您的要求。以下是 Maven2.0 的一些优点:
--
标准的项目布局和项目结构生成器
--
标准的依赖管理机制
--
多项目支持
--
在开发者需要的时候及时地下载新的插件和功能部件
--
生成最新项目信息的网站
--
集成了源代码控制软件: CVS Subversion

以上列表展示的只是 Maven2.0 特点中的一小部分。但这足以使 Maven2.0 成为一个构建管理系统可靠的选择。既然我们已经知道 Maven 是个什么东西了,接下来让我们看看如何使用它。

入门

我们要做的第一件事情就是设置目录结构,但这并不需要让我们手动设置, Maven 会根据您开发的项目类型来为您做这件事。一旦您下载并解压了最新发布的 Maven 2.0 ,您应该将 Maven 所在目录下面的 bin 目录添加到您的系统路径下。您可以运行命令 mvn -version 来测试您的安装。

既然已经安装上了工具,让我们看看创建一个简单的 Java 项目的例子。 Maven 使用原型来决定目录结构是如何展现的。 Maven 自带了几个内建的原型,您也可以自定义原型。

mvn archetype:create -DgroupId=com.oreilly -DartifactId=my-app

您看,这就生成了我们的项目布局。
my-app
----src
    ----main
        ----java
           ----com
               ----oreilly
    ----test
        ----java
            ----com
                ----oreilly

对,就这么简单。这种目录结构可以通过创建一个新的原型来覆写,但并不推荐这么做,因为 Maven 的一个优点就是使用标准的目录结构。该目录结构包含两个源代码树,一个是 Java 应用程序的源代码,另一个是单元测试代码。同时您也许会注意到,当第一次运行 Maven 的时候,它会进行一些下载工作 。当您开始调用工具时, Maven 会根据您使用的插件来更新自身的一些所需功能。 Maven 默认会从 Ibiblio 存储库中得到更新。您可以在 Maven 安装目录下的 conf 目录中,或者项目自身中修改 Maven 远程存储库的选择。
您会发现 Maven my-app 目录下创建了一个 pom.xml 文件。这是项目的最基本部分。 pom.xml 文件包含了一组指令,这些指令告诉 Maven 如何构建项目和包含哪些其它的特殊指令( POM 项目对象模型 的缩写)。在默认的情况下, Maven 包含了 JUnit 的依赖以此来鼓励单元测试。
<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>
  <groupId>com.oreilly</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Maven Quick Start Archetype</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>
</project>


创建完项目后,我们可以往项目里添加代码并使用 Maven 的所有全新技巧。注意以下命令必须在 pom.xml 文件所在的目录中运行。
--mvn test
:运行应用程序中的单元测试
--mvn package
:依据项目生成 jar 文件
--mvn install
:将项目的 jar 文件添加到库中, &#61548;         以备依赖此项目时使用
--mvn site
:生成项目相关信息的网站
--mvn clean
:清除目标目录中的生成结果
--mvn eclipse:eclipse
:生成 Eclipse 项目文件

接下来我们看看稍微复杂点的地方,我们知道手动开始一个 Java web 项目比手动开始一个简单的 Java 项目更耗时,然而 Maven 的使用则能化难为易。下面的例子(实际上是一行命令)展现了项目结构的构造。
mvn archetype:create -DgroupId=com.oreilly
    -DartifactId=Oreilly
    -DarchetypeArtifactId=maven-archetype-webapp


生成的结果结构如下所示:
Oreilly
----src
    ----main
        ----resources
        ----webapp
            ----WEB-INF

这一次,我们的项目由于支持了将包含在 war 文件中的 web 资源而设置有所不同。 pom.xml 文件中将包含一行来表明项目应该被打包成 war 文件: <packaging>war</packaging> 。现在就可以使用 mvn package 命令来生成 war 文件。不用担心如何从 WEB-INF/lib 目录中得到依赖项,在依赖属性值被设置成 compile 的情况下, Maven 会自动包含依赖项。也可以将以下代码添加到 pom.xml 文件中来改变 war 文件的名称:
<build>
    <finalName>PromoteC</finalName>
 </build>


依赖管理

创建好项目结构,添加完一些代码,测试并编译好应用程序后,接下来可以看看 Maven 是如何处理依赖关系的。为了给项目添加一个依赖项,必须将此依赖项添加到 pom.xml 文件中。下次运行 Maven 的时候,它将从 Ibiblio 存储库中得到这个依赖项,并且将此依赖项添加到项目构建路径中。

关于依赖的问题有几个重要的事情值得注意。在写这篇文章的时候, Maven 中最大的麻烦之处就是不能从 Maven 存储库中获取 Sun jar 文件 。这个问题归因于 Sun 在其代码中设置的许可证限制。解决这个问题的办法有两种,一种是下载这些代码并将它们安装在您本地的存储库中,另一种是做一个外部声明,并将这个声明指向文件系统中依赖项所在的位置。希望 Sun 能够尽早地创建自己的存储库,尽管如此, Maven 也会被升级来使之能够下载这些资源,只是在下载之前它会提示用户接受许可证协议。

另外一个麻烦的地方就是有时候使用的最新的库文件可能在远程存储库中不存在。另一种可能是由于无法访问 Internet ,需要所有的依赖项都能在本地获取。这些问题的最好解决方案就是将 jar 文件安装到本地的存储库中。将本地的存储库放在一台 web 服务器上也同样是个便利之举,这样整个开发团队就能从此获益,每个人都没有必要去管理自己的存储库了。改变 Maven 的存储库路径只需简单地编辑其安装目录下 conf 文件夹下面的 settings.xml 文件即可。

Maven 中使用依赖是简单的。让我们看看往上述 pom.xml 文件中添加一个依赖项的情况。我们虽然已经使用了 JUnit ,但让我们将功能强大的 Quartz 库添加到项目中。 Quartz 是一款用纯 Java 编写的关于时间安排的开源项目,它是您时间安排需求方面的很好的选择。
<dependency>
   <groupId>quartz</groupId>
   <artifactId>quartz</artifactId>
   <version>1.5.1</version>
   <scope>compile</scope>
 </dependency>


我们仅仅只需添加 <dependencies> 这个元素, Maven 就能下载 Quartz 并将其作为项目中的一个依赖项。不用担心 Quartz 的依赖项,一个 Maven 的存储库将包含依赖项自身依赖的资源信息,当 Maven 下载 Quartz 的时候,它自身的依赖资源也同样会被下载 。为了验证版本为 1.5.1 Quartz 存在于 Ibiblio 库中,我们可以浏览 Maven 存储库。注意到 scope 参数的使用,它告诉了 Maven 依赖项在何种阶段是所需的 。在使用 JUnit 的情况下,我们设置 scope 参数的值为 test 来告诉 Maven 这个依赖项只是在测试阶段所需的,而不是运行时所需的资源。以下是 scope 参数值的说明:
--compile
:默认值。表明是所有任务所需的资源
--test
:运行所有的测试用例时所需资源
--runtime
:表明是运行时所需资源
--provided
JDK 部分或应用服务器的 classpath 所需的资源

现在,如何处理那些麻烦的 Sun jar 包和那些需要但却不能在远程存储库中找到的 jar 包了?我们必须使用 Maven 来手动将这些 jar 包安装到本地的存储库中。不用担心,这没有听上去那么困难。为了做个示例,我们将安装 Java Activation 框架的 jar 包。首先我们必须从 Sun 的站点上下载此 jar 包,接着我们使用 Maven 将它导入本地的存储库中。您自己也可以按照 Maven 上传资源指南中的指导将缺少的 jar 包安装到 Ibiblio
mvn install:install-file -Dfile=activation.jar
    -DgroupId=javax.activation -DartifactId=activation
    -Dversion=1.0 -Dpackaging=jar


现在,新的 jar 包就像其它的项目依赖项一样安装到了本地存储库中。在只需添加依赖声明后,我们就已准备就绪了。在添加 jar 包和声明它们为依赖项时,必须确保版本信息的正确性。版本的不匹配会导致 Maven 在寻找资源时的失败。在导入 Sun jar 包时,如果您需要寻求标准命名参数的帮助,可以参考 Sun 标准 jar 包命名。记住,在目前您不能通过存储库来公开发布这些 jar 包,这将违反 Sun 的使用条款
<dependency>
   <groupId>javax.activation</groupId>
   <artifactId>activation</artifactId>
   <version>1.0</version>
   <scope>compile</scope>
 </dependency>


您或许想将依赖项存入一个源代码控制器的库中,源代码控制器决不能执行这个任务。依赖项是经常变化的,并且通常有一套数字方案来标明其版本。这就是说,您明确地希望有一个内部远程存储库的备份,如果您有一个,这将确保在存储库服务器崩溃并且不能恢复的情况下,您不会丢失所有的自定义资源。不将依赖项放入源代码控制器中也会节省源代码控制器的存储库服务器上的大量磁盘空间。

配置存储库

要求项目的每个开发者必须在 conf 目录中配置存储库是不方便的,所以 Maven 可以同时查看多个存储库并且将它们全部配置在 pom.xml 文件中。让我们看看一个例子,它展示了如何在应用程序用使用多个存储库。在以下从 pom.xml 文件摘录的片断中,我们设置了两个存储库来让 Maven 寻找依赖项。 Ibiblio 一直是默认的存储库,我们又添加了 Planet Mirror 作为后援存储库。我们也可以让团队使用的本地 web 服务器作为第二个存储库。
<repositories>
    <repository>
      <id>Ibiblio</id>
      <name>Ibiblio</name>
      <url>http://www.ibiblio.org/maven/</url>
    </repository>
    <repository>
      <id>PlanetMirror</id>
      <name>Planet Mirror</name>
      <url>http://public.planetmirror.com/pub/maven/</url>
    </repository>
  </repositories>


使用 pom.xml 父文件来构建多个项目

软件公司通常的一种做法就是将多个项目构建到主要产品中。维护依赖关系链和一次性地构建整个产品足以成为一个挑战,但是如果使用 Maven 的话,事情将变得简单。如果您创建了一个指向其它子模块的 pom.xml 父文件, Maven 将为您处理整个构建过程。它将分析每个子模块的 pom.xml 文件,并且按照这些子模块的相互依赖顺序来构建项目。如果每个项目明确地指明它们的依赖项,那么子模块在父文件中的放置顺序是不造成任何影响的。但是考虑到其他的开发者,最好保证子模块在 pom.xml 父文件中的放置顺序和您期望的子项目被构建的顺序一样。下面我们看个示例。
pom.xml
主文件如下:
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.oreilly</groupId>
  <version>1.0-SNAPSHOT</version>
  <artifactId>my-app</artifactId>
  <packaging>pom</packaging>
  <modules>
    <module>Common</module>
    <module>Utilities</module>
    <module>Application</module>
     <module>WebApplication</module>
  </modules>
</project>


我们需要确保 WebApplication 子模块包含了所有的三个 jar 包,所以需要将这些 jar 包声明为依赖项。在这个例子中, Utilities 项目依赖于 Common 项目,所以 Utilities 项目中需要添加一个对 Common 项目的依赖。 Application 子模块也是同样的道理,因为它依赖于 Common Utilities 项目, Utilities 又赖于 Common 。如果这个例子中有 60 个子模块,并且它们都相互依赖,这会使得新开发者难以算出什么项目依赖于其它项目,所以这正好是要求确保 pom.xml 父文件中项目放置顺序要清除的原因。

以下是 Utility 模块的依赖项:
<dependencies>
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Common</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>


以下是如何声明 Application 模块的依赖项:
<dependencies>
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Common</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Utilities</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>


最后是 WebApplication 模块的依赖项:
<dependencies>
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Common</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Utilities</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    
    <dependency>
      <groupId>com.oreilly</groupId>
      <artifactId>Application</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    
 </dependencies>


现在,我们只需为每个子模块的 pom.xml 文件添加一个元素来表明它们是一个逻辑构建的一部分
<parent>
    <groupId>com.oreilly</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>


pom.xml 父文件所在的同一个目录中,存在有项目目录: Common, Utilities, Application, WebApplication 。当我们在该目录中运行 mvn package 命令时,这些项目会按照依赖顺序而被构建。

插件和报表

Maven2.0
有大量的插件可以使用。不幸的是,由于 Maven 的重写, Maven1.0 的插件不能在 2.0 中使用。尽管如此,还是存在一些可以使用的 Maven2.0 的插件。下面 pom.xml 文件中的插件配置示例是直接从 Maven2.0 网站上得来的。这个插件是用来配置编译选项的。
<plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>


Maven
报表插件可以用来生成不同的报表,这些报表是在当你使用 mvn site 命令生成项目的站点时产生的。下面的例子展示了如何使用 <reporting> 元素来配置这类插件中的一个。
<reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
      </plugin>
    </plugins>
  </reporting>


Maven Plugin Matrix
是一个十分实用的工具,它能给出哪些 Maven 插件适合于哪些版本的 Maven

Maven Eclipse

如何能使全世界最好的 IDE 变得更好了?答案是使用 Maven2 的插件,它能帮助您寻找依赖项并自动地将它们添加到 pom.xml 文件中 虽然最好的方法是首先使用 Maven 来创建您的项目,然后再用命令 mvn eclipse:eclipse 来生成 Eclipse 项目文件,这样最初就能得到一个好的目录结构,但 Maven 也可通过其 Eclipse 插件来管理任何项目

您可以在 Eclipse 自身的升级器中输入站点 http://m2eclipse.codehaus.org/ 来安装插件。在安装完成并重启 IDE 后,您需要在 Eclipse 的参数选项中配置此插件,设置本地存储库的位置。这是很重要的一步,因为如果 Eclipse 默认的存储库不能匹配您默认的需求, Maven 会重新下载您的依赖项。配置完成后,将项目导入 Eclipse ,鼠标右击该项目,选择 Maven 2 -> Enable 。现在您可以回到之前的步骤,您可以有更多的选项比如添加依赖项,这将弹出一个搜索框,您可以搜索依赖项并添加它们,插件会替你编辑 pom.xml 文件。

插件会使用 Maven 来构建您的项目,就像 Eclipse 使用 Ant 来构建项目一样。如果您想获取更多的关于 Eclipse 整合 Maven 的信息,可以查阅 Maven 站点上的 Eclipse 集成 Maven 2.x 使用指南。

另一方面,如果您是一个 IntelliJ 使用爱好者,您也能通过运行指令 mvn idea:idea 来完成同样的任务。这些 IDE         工具能够节省开发人员的时间。例如,如果一个开发人员为一个项目添加了一些特征,团队里的其他开发人员只需从源代码控制器的存储库中重新获取项目文件即可,这就节省了每个开发人员必须配置 IDE 的时间。

结论

Maven2.0
有着许多实用的特点,并且完成任务十分出色。 Maven 中最值得称赞的地方就是使用了标准的目录结构和部署 。这就使得开发人员能够适应不同的项目,并且不用学习任何结构方面新的东西,也不用掌握特殊的指令来构建结构。 Maven 可以通过纯脚本来实现。在文档方面,由于使用了项目站点构建工具,所以当项目构建完成后,您可以查看所有开发的当前状态。

毫无疑问,当提到构建配置的伸缩性,易用性和项目管理方面时, Maven2.0 足可以将 Ant 取而代之。在接下来的几年内,我们将看到 Maven 作为标准构建技术更多的使用,直到有人带来了大家公认的 高级捕鼠器 。您可以从下面列出的 Maven 项目站点上下载 Maven

资源
Matrix:http://www.matrix.org.cn
Onjava:http://www.onjava.com
Maven
项目站点

Chris Hardin
McLeod 软件公司的高级 Java 工程师。 

你可能感兴趣的:(Maven 2.0:编译、测试、部署、运行)