天天看点

开始使用Maven(上)

节选自O'Reilly出版的<<开发人员的笔记本:Maven>>

作者:帝默西 M.奥波莱恩,文森特.马索尔。

翻译:phynalica

如有问题,或发现错误及不妥之处,请联系笔者:[email protected]

编辑笔记:

        当你为了完成编译代码、生成JAR或WAR文件以及生成Javadocs等工作,而第十次编写同样的Ant targets时,你肯定希望有一种更省事的方法来完成这些事情。Maven提供了这样的选择,并且把你的工作从任务级别提高到项目管理级别。因为Maven项目已经知道如何编译和绑定代码、运行测试、生成文档以及如何安置项目网页。

        O'Reilly出版的<<开发人员的笔记本:Maven>>有助于组织项目以及加快进度,并且对Maven的高级特性进行了深入地研究,如Maven的插件以及对于团队合作开发的支持。在示例章节“Maven 起步”中,作者文森特.马索尔和帝默西 M.奥波莱恩将会告诉你如何安装Maven、如何开始你的第一个项目,还有如何开始研究Maven用于与IDE和源代码控制系统进行集成的特性。

        文森特.马索尔是Jakarta Cactus框架的创建者,他在Maven项目的早期就非常活跃。文森特曾经在几个主要项目(多数为J2EE)中,担任了四年的技术架构师,现在他是Pivolis公司的创始人之一,同时兼任CTO(高级技术主管)。Pivolis公司是一家专门应用敏捷方法开发软件的公司。文森特现在住在法国巴黎的莱特城,他的网址是www.massol.net 。

        帝默西 M.奥波莱恩住在一利诺斯州的芝加哥,他是一名开发人员,也是一位企业家。他经常使用的编程语言是Java、Python和Ruby。

我们即将开始使用Maven。到本章结束的时候,你应该已经知道如何创建Maven项目,如何使用Maven来管理依赖项,以及如何使用一些有趣的报表来创建一个简单的项目网站。

作者:phynalica; phynalica

原文: http://www.matrix.org.cn/resource/article/2006-10-27/Maven_d91b7923-6510-11db-bdce-bdc029e475a1.html     安装Maven

在开始以前,必须得安装一些先决条件。Maven兼容Java1.4.2和1.5.0,本书中的示例使用的是Java1.4.2。本书完成时,Maven的最新版本为Maven1.0.2。除了JDK和Maven1.0.2,你还得连接到互联网,因为Maven会在需要的时候,从公共网站上下载依赖项。好吧,我们开始安装。

提示

本书中涉及到的一些插件没有与Maven1.0.2捆绑在一起。详细的

Maven插件安装说明,请参考第六章以及附录A中详细的插件列表。

安装步骤

从Apache Software Foundation(ASF)下载Maven。打开网址http://maven.apache.org/,从左边的导航菜单上找到“Getting Maven”,然后选择“Downloading”,在打开的网页中,有四种格式的文件可供下载:Windows安装包、.zip文件、tar’d.bzip文件、tar’d.gzip文件,根据你所使用的平台,下载合适的文件。

如果是微软的Windows平台,请下载Windows安装包(maven-1.0.2.exe),下载后自动安装,按照安装指导安装就可以了。安装完成后,打开控制面板->系统->高级,单击按钮“环境变量”,在用户变量中添加名为“MAVEN_HOME”的环境变量,值为安装Maven的目录。然后把“%MAVEN_HOME%/bin”添加到环境变量PATH中。打开命令提示符,如果成功安装了Maven,你会看到这样的输出:

C:/dev/mavenbook/code>maven –v

__ __

| // |__ _Apache__ ___

| |//| / _` / V / -_) ' / ~ intelligent projects ~

|_| |_/__,_|/_//___|_||_| v. 1.0.2

        如果你要将Maven安装到C:/Program Files/Apache Software Foundation/Maven1.0.2以外的目录中,你也可以下载Maven1.0.2.zip,解压到任何一个目录中都可以。然后将环境变量“MAVEN_HOME”指向解压后的文件所在的目录,并把“%MAVEN_HOME%/bin”添加到环境变量PATH中。

        如果你用的是Unix平台,应该下载tar'd.gzip文件(maven-1.0.2.tar.gz),并使用命令“xvzf maven-1.0.2.tar.gz”将下载的文件解压到你所选择的目录。在这里,我们假设文件被解压到目录“/usr/local/maven-1.0.2”。然后你要设置两个环境变量:MAVEN_HOME和PATH。以下命令把它们设置为合适的值:

        [[email protected] tobrien]$ export MAVEN_HOME=/usr/local/maven-1.0.2

        [[email protected] tobrien]$ export PATH=${PATH}:${MAVEN_HOME}/bin

        如果Maven成功地安装到了你的机器里,你会看到与安装了Windows的机器一样的输出。

        祝你安装成功!

提示

有些人喜欢把本机应用程序安装在Unix的“a/opt”目录下,Windows的c:/apps

目录下。其实你把Maven安装到哪里都可以。

回顾

你刚才安装了Maven1.0.2,并且配置了一些环境变量。设置了MAVEN_HOME,并且把maven.bat 或是maven.sh包含在PATH中,你应该就可以完成本书中的示例了。

关于Maven2

现在是个提及Maven2(有时也称作“m2”)的好时机。Maven2完全重写了Maven1。重写的主要目的是提供一个强大的Java build和 project comprehension API,以使Maven可以嵌入到任何地方,尤其是一些高级产品,如:集成开发环境、质量检查工具以及报表工具等等。Maven2正式提出了build的生命周期这一概念,而且,Maven2比Maven1更容易扩展。

Maven1和Maven2有很多相同的概念,但它们也有一些明显的区别。有关Maven2的更多信息,请关注Maven网站:http://maven.apache.org/,下载Maven2的预发布版本。并加入Maven用户和开发者邮件列表。如果你听说过“持续集成”,你也许想看一下Maven的子项目-Continuum,网址是http://maven.apache.org/continuum。

新建项目

        建立一个新项目的难度取决于创建“开发基础设施”时所做出的努力。“开发基础设施”指的是自动自动编译,单元测试,文档,项目报表等。使用Maven,你可以生成一个框架项目来加快这个过程,这个框架项目可以做为新应用程序的种子。

步骤

        Maven有一个“Application Generation”插件(Genapp),你可以使用它来创建一个新项目。

        首先要创建一个空目录:c:/dev/mavenbook/code/genapp/test-application,生成的应用程序将会放在这个目录下。然后通过执行Maven命令genapp,来选择默认模版,并提供一些关于新项目的信息来运行Genapp插件:

C:/dev/mavenbook/code/genapp/test-application>maven genapp

| // |__ _Apache__ ___

| |//| / _` / V / -_) ' / ~ intelligent projects ~

|_| |_/__,_|/_//___|_||_| v. 1.0.2

        Attempting to download commons-jelly-tags-interaction-20030211.143817.jar.

4K downloaded

Enter a project template to use: [default]

Enter

Please specify an id for your application: [app]

test-application

Please specify a name for your application:  Example Application

Test Application

Please specify the package for your application: [example.app]

mdn.testapp

build:start:

genapp:

[copy] Copying 1 file to C:/dev/mavenbook/code/genapp/test-application/

src/java/mdn/testapp

[copy] Copying 3 files to C:/dev/mavenbook/code/genapp/test-application/

src/test/mdn/testapp

[copy] Copying 1 file to C:/dev/mavenbook/code/genapp/test-application/

[copy] Copying 2 files to C:/dev/mavenbook/code/genapp/test-application/

BUILD SUCCESSFUL

        这个插件要求用户输入一些信息,从上面的输出中可以看出,你正在使用默认的应用程序模板,并且提供了应用程序ID、应用程序名称以及新项目所使用的包。默认的应用程序模板创建了一个单独的类:mdn.testapp.App,这个类含有一个静态的主函数,两个JUnit测试。

Maven的插件“生成应用程序”产生了以下文件和目录:

test-application/

project.properties

project.xml

src/

conf/

app.properties

java/mdn/testapp/

App.java

test/mdn/testapp/

AbstractTestCase.java

AppTest.java

NaughtyTest.java

        所有的Maven项目都有标准的目录结构,这种目录结构在项目的项目对象模型(POM)中有所涉及,我们马上会学到。如果你想把一些写好的类添加到项目中,你得把它们放到src/java目录下;如果是单元测试,就得放到src/test目录下。有时这些写好的类和单元测试要依赖于一些外部类库,我们将在后面的部分学习如何添加依赖项。目录xdoc中含有XDoc格式的项目文档。

提示

请注意,Maven-1.0.2所附带的这个版本的Genapp插件创建了非标准的项目布局。

所以,把Maven项目的源代码和单元测试放在src/java目录和src/test目录已经不合适了。应该使用src/main/java目录和src/test/java目录。要达到这个目的,必须要修改project.xml文件。把src/java的引用改为src/main/java,把src/test的引用改为src/test/java。获取更多的信息,请看“Maven惯例”,网址:http://maven.apache.org/reference/conventions.html。

        project.xml是项目的描述文件;这是一个含有项目对象模型(POM)的XML文件。我们来看一下为这个项目定制的project.xml文件的副本:

<project>
<pomVersion>3</pomVersion>
<artifactId>test-application</artifactId>
<name>Test Application</name>
<currentVersion>1.0</currentVersion>

<organization>
<name>Your Organization</name>
<url>http://www.someorganization.biz/</url>
<logo>http://www.someorganization.biz/logo.gif|jpg|...</logo>
                </organization>

                <inceptionYear>2005</inceptionYear>

                <package>mdn.testapp</package>

                <logo>http://yourproject/logo.jpg|gif|...</logo>
                <description>
                        An example project
                </description>
                <shortDescription>
                        How to use maven in different situations
                </shortDescription>
                <!--许多元素被省略(见生成POM) -->
                <dependencies/>

<build>
        <sourceDirectory>src/java</sourceDirectory>
        <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
        <unitTest>
                <includes>
                        <include>**/*Test.java</include>
                </includes>
                <excludes>
                        <exclude>**/NaughtyTest.java</exclude>
                </excludes>
        </unitTest>
<resources>
        <resource>
                <directory>src/conf</directory>
                <includes>
                        <include>*.properties</include>
                </includes>
        </resource>
        </resources>
        </build>
</project>      

        这个文件告知Maven关于项目的所有信息。build元素定位源代码、单元测试以及将会与应用程序一起打包的资源。Name、artifactId、currentVersion,、inceptionYear,、description,

和 shortDescription确定了项目,并且提供了信息,用来命名从项目创建的artifact。

注释:artifact指的是某一特定项目的输出,包括JAR、WAR、SAR、RAR等。

提示

如果你使用了已有的Maven项目,在元素artifactId的位置,你看到的是元素id。

我们不推荐使用元素id,你应该使用元素artifactId。

        resources元素被JAR插件用来把资源复制到JAR artifact。在这个元素中,你在resource标签中指定了一组资源。在这个示例中,来自src/conf目录的资源将被复制到类路径(classpath)的根目录。也就是说,资源app.properties将会被复制到生成的JAR artifact的根目录。如果你想让src/conf目录下所有的.properties资源和.xml资源在生成的JAR包mdn.testapp中可用,就得用以下方法指定一个目标路径(targetPath):

        
<resource>
                <directory>src/conf</directory>
                <targetPath>mdn/testapp</targetPath>
                <includes>
                        <include>*.properties</include>
                        <include>*.xml</include>
                </includes>
</resource>      

        project.properties可以使你为特定项目定制Maven和Maven插件的行为。在本书后面的部分,我们将会使用这个文件来给生成的网页定制外观,给JAR文件定制内容。

提示

Maven还有很多在线文档,这里是一篇不使用Genapp插件创建新项目的快速入门指南,

“十分钟测试”,作者:布莱特.波特,网址:http:// maven.apache.org/start/ten-minute-test.html。

关于Maven追踪合作项目信息的能力

                为了简化这个示例,我们从原来的project.xml文件中删除了一些元素,原来的project.xml文件描述了邮件列表、源代码库、开发者和网站。在第四章和第五章中,我们将会更加详尽地学习如何使用Maven来发布网站以及如何使用Maven与现有的源代码库一起工作。

通过代理使用Maven

                Maven依赖于互联网,它会通过HTTP下载所有的依赖项和插件。如果你在像公司一样的环境中工作,你可能需要配置Maven,以使它能够通过代理服务器来工作。

步骤

                你需要在项目的project.properties文件中设置一些属性。project.properties文件允许你通过设置已命名的属性,来定制Maven的行为。要想配置代理服务器,必须把以下的project.properties文件与项目的project.xml文件放在同一个目录下:

maven.proxy.host = proxy.company.com
                maven.proxy.port = 80      

这些属性配置了Maven,使它可以连接到proxy.company.com这台机器的80端口上。如果你使用了要求验证的代理服务器,你必须指定两个额外的属性:

maven.proxy.username = tobrien
                maven.proxy.password = [email protected]      

如果你要连接要求NTLM验证的代理服务器,请设置如下属性:

maven.proxy.ntlm.username = tobrien
                maven.proxy.ntlm.password = [email protected]      

提示

在第二章中,你将会了解到:像这样特定用户的属性,应该定义在~/build.properties文件中,或者%USERPROFILE%/build.properties文件中。现在,如果你想在防火墙后面完成这个示例,就把这些属性定义在project.properties文件中。

项目的编译和测试

        你现在有一个新项目,它有一个类和一个单元测试。接下来,让我们编译项目,并运行App类。

步骤

        执行Maven命令jar:jar,以此来创建一个JAR文件,这个JAR文件包含这个应用程序的类。JAR插件定义了一个快捷命令jar,它依赖于jar:jar命令。执行任意一个将获得相同的结果。所有的插件都定义了快捷命令。例如,test命令执行Test插件的test:test命令。使用maven jar来执行jar命令:

C:/dev/mavenbook/code/genapp/test-application>maven jar

__ __

| // |__ _Apache__ ___

| |//| / _` / V / -_) ' / ~ intelligent projects ~

|_| |_/__,_|/_//___|_||_| v. 1.0.2

Attempting to download junit-3.8.1.jar.

118K downloaded

build:start:

java:prepare-filesystem:

[mkdir] Created dir: C:/dev/mavenbook/code/genapp/test-application/

target/classes

java:compile:

[echo] Compiling to C:/dev/mavenbook/code/genapp/test-application/

target/classes

[echo]

[javac] Compiling 1 source file to C:/dev/mavenbook/code/genapp/testapplication/

target/classes

java:jar-resources:

Copying 1 file to C:/dev/mavenbook/code/genapp/test-application/target/

classes

test:prepare-filesystem:

[mkdir] Created dir: C:/dev/mavenbook/code/genapp/test-application/

target/test-classes

[mkdir] Created dir: C:/dev/mavenbook/code/genapp/test-application/

target/test-reports

test:test-resources:

test:compile:

[javac] Compiling 3 source files to C:/dev/mavenbook/code/genapp/testapplication/

target/test-classes

test:test:

[junit] Running mdn.testapp.AppTest

[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.078 sec

jar:jar:

[jar] Building jar: C:/dev/mavenbook/code/genapp/test-application/

target/test-application-1.0.jar

BUILD SUCCESSFUL

Total time: 9 seconds

        Maven创建了名为target的目录来放置中间文件和JAR文件。创建了JAR文件之后,按照如下方式执行App类:

C:/dev/mavenbook/code/genapp/test-application> java ^

More? target/test-application-1.0.jar mdn.testapp.App

Hello World!

        如果你想重新来一遍,运行maven clean来删除target目录,然后重新编译。

注释:        ^和more的意思是DOS命令行要继续执行。

Maven 开始工作了,第一次,它要运行单元测试。如果本机没有安装JUnit,它会自动下载。不必在网上搜索JAR文件。

回顾

        运行jar命令时,Maven使用JAR插件创建了一个JAR artifact。首先,Maven必须运行一系列命令,才能创建本程序的JAR文件。JAR插件有一个jar:jar命令,这个命令又依赖于其它的命令。Maven运行了如下一系列命令:java:prepare-filesystem,java:compile, java:jarresources,test:prepare-filesystem,test:test-resources, test:compile,and test:test。

        Maven 运行了Test插件的一个命令,这个命令执行JUnit测试,并且检查本机的Maven库里是否含有JUnit 的JAR文件。因为Maven在第一次使用时,会从Maven 的默认库http://www.ibiblio.org/maven/  下载junit-3.8.1.jar 。

        在本章后面的部分,你将学到本地Maven库和Maven强大的依赖项管理能力。

使用项目对象模型

        项目对象模型(POM)是Maven中最重要的部分,你将在本书中学会使用它。

如何使用POM

        POM也叫做项目描述文件。project.xml中的XML元素描述了项目的源代码、开发者、源代码控制、许可以及确认信息,如项目名称、赞助项目的组织名称。Maven的POM是编译系统得一个突破。Maven没有给每一次编译提供具体的说明,而是采用了声明的方式。也就是说,你不必告诉Maven去做什么,因为Maven会根据project.xml去寻找。另一方面,Ant是一种需要立刻处理的编译项目的方式,你得告诉Ant去编译一个类、建立一个目录、把文件打包成WAR。Maven维护多个插件,这些插件被设计用来与标准POM一同工作。标准POM是指结构、验证和内容的声明。

        如果你看一下上一个练习生成的project.xml文件,你会发现很多元素在上面的讨论中被忽略了。下面的XML以被期望的顺序列出了POM中的顶层元素:

<project>
<extend/>
<pomVersion/>
<id/>
<name/>
<groupId/>
<currentVersion/>
<organization/>
<inceptionYear/>
<package/>
<logo/>
<gumpRepositoryId/>
<description/>
<shortDescription/>
<url/>
<issueTrackingUrl/>
<siteAddress/>
<siteDirectory/>
<distributionSite/>
<distributionDirectory/>
<repository/>
<versions/>
<branches/>
<mailingLists/>
<developers/>
<contributors/>
<licenses/>
<dependencies/>
<build/>
<reports/>
<properties/>
</project>      

本章将学习上面的XML文件中的大多数元素,包括contributors,developers,dependencies,reports,and repository。本章中的示例将提供详尽的细节,但你应该使用上面的XML文件节选,把元素放在project.xml中的合适位置。

列出可用的goals(Maven命令)

        当你使用Maven的时候,其实就是在执行goals。Maven的插件就是一组相关的goals。例如,要从项目创建一个JAR文件,你得像这样执行JAR插件的jar:jar:

        C:/dev/mavenbook/code/genapp> maven jar:jar

        冒号前面的jar表示这个Maven命令属于JAR插件。要想查看JAR插件的所有Maven命令,输入以下命令:

C:/dev/mavenbook/code/genapp> maven -P jar

__ __

| // |__ _Apache__ ___

| |//| / _` / V / -_) ' / ~ intelligent projects ~

|_| |_/__,_|/_//___|_||_| v. 1.0.2

Goals in jar

============

[jar] Create the deliverable jar file.

deploy ......................... Deploy a jar to the remote repository

deploy-snapshot ................ Deploy a snapshot jar to the remote

repository

install ........................ Install the jar in the local repository

install-snapshot ............... Install a snapshot jar in the local

repository

jar ............................ Create the deliverable jar file.

snapshot ....................... Create a snapshot jar, ie '

id-YYYYMMDD.hhmmss.jar'

Plugin for creating JAR files. Requires Maven 1.0 RC2.        

        如果你需要查看可用的插件和goal的列表,输入以下命令:

                C:/dev/mavenbook/code/genapp/test-application> maven -g | more

插件的整个列表太长了,因为Maven的插件功能全面,从为不同的IDE生成项目文件到生成WAR文件,再到启动和关闭应用程序服务器。在接下来的事例中,我们将学习一些更有用的插件。

注释:以上输出中的Goals就是指Maven命令。

生成Debug信息

        现在,你可能已经注意到了,Maven做了大量“繁重的”工作。如果你正在使用Ant,你就得编写Ant的build.xml文件,并且添加需要编译的任务、jar和单元测试。Maven降低了复杂程度,但是当面对DEBUG时,就应该观其细节。Maven可以在DEBUG模式下运行,并且打印出编译的每一个细节,如果你要确认每一次编译是否准确地如你所愿地进行了,这样的功能是十分有用的。

步骤

        在这个示例的一开始,让我们再看一下上一个测试程序,当运行maven test命令时,输出如下:

java:compile:

[echo] Compiling to C:/dev/mavenbook/code/genapp/test-application/

target/classes

[echo]

java:jar-resources:

[...]

在java:compile 命令或者java:jar-resources命令执行的时候,到底发生了什么?运行maven –X test 命令将会显示在Maven编译时,所有被执行的命令的DEBUG信息。让我们试一下,只使用前面列出的三个命令。运行maven –X test,产生如下输出:

[...]

java:compile:

[echo] Compiling to C:/dev/mavenbook/code/genapp/test-application/

target/classes

[javac]  DEBUG  fileset: Setup scanner in dir

C:/dev/mavenbook/code/genapp/test-application/src/java with

patternSet{ includes: [ ] excludes: [**/package.html] }

[javac]  VERBOSE  mdn/testapp/App.java omitted as mdn/testapp/App.class

is up to date.

java:jar-resources:

DEBUG  FileSet: Setup scanner in dir

C:/dev/mavenbook/code/genapp/test-application/src/conf with

patternSet{ includes: [*.properties] excludes: [ ] }

VERBOSE  app.properties omitted as app.properties is up to date.

[...]

Java:compile命令的输出看上去很熟悉。它们是Ant的echo和javac命令的输出。正如在第二章中解释的那样,Maven经常使用Ant的命令来执行像复制、删除、编译以及创建JAR文件等一般操作。

回顾

你所执行的两个命令,产生了简单的DEBUG输出。Java:compile命令只是扫描了放置源代码的目录,检查是否有比与Java源代码有关联的类文件更新的Java源代码。Java:jar-resources命令寻找资源,并把找到的资源放入JAR文件中。像test:test这样更复杂的命令将会产生虚拟机和类装载器(class loader)的DEBUG信息。

        当Maven出现问题时,或是命令抛出异常时,Maven只会打印出一条很短的消息,告诉你出错了。如果你需要更多的信息,并且想看一下堆栈追踪,就在命令行上添加-e标志。有了-e标志,Maven在遇到错误时,就会打印出完整的堆栈追踪。

添加依赖项

        现在,你有了一个含有一个类的项目,你已经成功编译并运行了这个类。接下来,你要在项目描述文件中添加一个依赖项,并开始使用Maven来管理项目依赖项。考虑到这个lab的目的,我们假设你使用了Spring 框架。然后再Spring框架的两个artifact :spring-core-1.1.4.jar和web-1.1.4.jar上添加一个依赖项。

步骤

        首先,你得在Maven的默认中心库中找到你需要的JAR文件,URL为http://www.ibiblio.org/maven/ 。在浏览器中打开这个地址,你将看到一系列目录,我们需要的目录是springframework,它的子目录的结构如下:

http://www.ibiblio.org/maven

/springframework

/jars

spring-core-1.1.4.jar

spring-dao-1.1.4.jar

spring-web-1.1.4.jar

        要依赖一个artifact,你要在dependency元素中,使用这三个元素:groupId,artifactId和version。你可以在两个artifact上添加依赖项,方法是:用下边的XML替换掉 test-application/project.xml中的dependencies元素。

<dependencies>
<dependency>
<groupId>springframework</groupId>
<artifactId>spring-core</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>springframework</groupId>
<artifactId>spring-web</artifactId>
<version>1.1.4</version>
</dependency>
</dependencies>      

        现在,运行jar命令,并留意一下Maven的输出;它应该包含一些像下面这样的输出:

Attempting to download spring-core-1.1.4.jar.

266K downloaded

Attempting to download spring-web-1.1.4.jar.

111K downloaded

        图1-1显示了下面的一系列由jar命令引发的事件:

1.        Maven 搜索project.xml中定义的POM,找到了springframework组中两个artifact的依赖项。然后Maven开始在Maven本地库中寻找spring-core-1.1.4.jar和spring-web-1.1.4.jar。

2.        Maven没有找到这些文件,所以它去http://www.ibiblio.org/maven/springframework/jar/ 获取这两个JAR文件。然后这些文件被下载下来,放到你的Maven本地库中,同时也被添加到项目的类路径(classpath)中。你的项目再需要这两个文件时,Maven将会到本地库中去获取。

开始使用Maven(上)

图1-1 Maven的本地库(Local Repository)和远程库(Remote Repository)为项目test-ap-

Plication提供sping框架的JAR文件。

回顾

        Maven为你降低了难度,节省了时间。在Maven出现以前,依赖项通常与项目捆绑在一起,放在lib目录下,还有一种情况就是,一个项目会有一些说明,教你如何把正确的JAR文件添加到类路径(classpath)中。用Maven来管理依赖项有着明显的优势。对于初学者来说,如果你的项目要依赖30个外部的JAR文件,没有必要把这么多文件放到源代码控制库中,这样会节约存储空间,而且,当你需要从源代码控制系统中检出项目时,下载速度也会更快。此外,如果你有多个项目依赖相同的外部文件,Maven会一次把它们都下载下来,而且之下载一次,你的每一个项目,会引用本地Maven库中的依赖项的一个单独的副本。如果可以从远程Maven库中下载依赖项,我们没有什么特别的理由要存储这些依赖项并区分它们的版本。

        当Maven下载依赖项时,其实它把文件从远程Maven库中复制到本地机器上本地Maven库。Maven是如何找到依赖项的?它是依靠project.xml中dependency元素所提供的信息做到的。如图1-2所示。

开始使用Maven(上)

图1-2 Maven库(Repository)和项目对象模型(POM)之间的映射。

指定了groupId,Maven会去查找指定的目录-springframework。指定了type,Maven会去查找指定的子目录,如jars或是wars(请注意Maven在type元素后面添加的字母“s”);在这种情况下,type会被忽略掉,因为JAR是默认类型。指定了artifactId,Maven就会知道从jars目录下载哪一个文件。顶层目录-springframwork代表group的标识符,JAR文件的文件名的第一部分代表artifact的标识符,最后一部分,去掉扩展名,代表version的标识符。Maven使用以下方式来解析Maven库中的一个依赖项,其中的[REPO_ROOT]是指远程Maven库的URL:

        [REPO_ROOT]/<groupId>/<type>s/<artifactId>-<currentVersion>.<type>

提示

在Maven2.0中,Maven库的结构将更像JAVA包的结构。在预计的结构中,

groupId将不会是springframework,而是org.springframework。此外,每一个

版本都有一个单独的目录,这样可以提高Maven库的效率。了解更多变动的

信息,请访问

http:// docs.codehaus.org/display/MAVEN/Repository+Layout+-+Final。

        Maven在你的主目录下维护一个本地库,以此来处理依赖项。在装有Unix的机器上,你的Maven库位于~ /.maven/repository目录;在装有Windows的机器上,Maven库位于你的%USERPROFILE%目录下。如果你查看一下你的本地Maven库,你会发现里面有一个springframework目录。在%USERPROFILE%/maven/repository/springframework/jars含有spring-core依赖项的两个文件:spring-core-1.1.4.jar和spring-core-1.1.4.jar.md5文件,后者含有MD5哈希,用来确保spring-core的JAR文件的完整性。现在的Maven1没有使用MD5来验证artifact的完整性。但是以后的版本可能要使用MD5来验证下载的artifact。

提示

在Windows机器上,%USERPROFILE%目录通常被分解为像这样的一个目录:

C:/Documents and Settings/vmassol。%USERPROFILE%被用作Unix主目录的缩写。

关于id元素的使用

        如果你要管理现有的项目,你可能会有一些使用id 元素的依赖项。下面的dependencies元素演示了如何使用一个单独的id元素来依赖1.0版的Jakarta Commons Math:

<dependencies>
<dependency>
<id>commons-math</id>
<version>1.0</version>
</dependency>
</dependencies>      

        只使用id元素的话,只有在groupId与artifactId相匹配的时候才有效,如果你浏览Maven库,你会看到如下的目录结构:

/commons-math

/jars

commons-math-1.0.jar

commons-math-1.1.jar

然而一个单独得id元素会有效,我们不推荐这样的做法,在Maven2中将不会有这种情况。你可能在其它的项目中也见过这样的做法,但请尽量使用groupId和artifactId来确认依赖项。

依赖Snapshots

        如果你正在开发一个带有依赖项的程序,而它的依赖项会经常变化,你可能想要依赖最新的编译结果,而不是给每一个依赖项硬编码一个版本。当一个项目的依赖项仍然是测试版时,或者正如第三章讨论的那样,你正在开发一系列互相依赖的Maven项目,这就非常有用了。在这一节的示例中,你将学会如何依赖SNAPSHOT。

步骤

                不必指定依赖项的特定版本,只要把关键字SNAPSHOT作为版本名称的一部份就可以了。每当执行一个Maven命令的时候,Maven会检查远程Maven库,看有没有依赖项的新版本。如果Maven找到了比本地Maven库中的依赖项更新版本,Maven就会把它下载下来。例如,下边的依赖项总是下载最新的spring开发用JAR1.2:

<dependency>
<groupId>springframework</groupId>
<artifactId>spring</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>      

总结

                使用SNAPSHOT依赖项,其实就是告诉Maven使用远程Maven库中的最新版本。

当你使用Multiproject插件的时候,当你的项目要依赖于还处于开发阶段的artifact时,或者,你所在的开发团队的人数不少,这样的功能就会十分有用。如果你的项目要依赖于某一个组件开发版或者未发行版,这个时候就会用到SNAPSHOTY依赖项。SNAPSHOT依赖项应该只为开发意图服务。作为一项规则,你绝不能发布一个依赖于SNAPSHOT依赖项的项目。

离线编译

如果你要在断开网络的情况下使用Maven,那就得让Maven不检查是否存在SNAPSHOT依赖项的最新版本。本节将教你如何使用Maven进行离线编译。

步骤

                过程很简单:使用命令行选项-o。例如,你不能上网,但你想执行test命令,运行maven –o test,它就会在不检查依赖项的情况下执行test命令。如果你的项目不必依赖于SNAPSHOT来编译,即使在不上网的情况下,也不用在命令行添加-o。如果项目依赖于SNAPSHOT来编译,你就得在命令行添加-o。因为Maven每执行一个命令,它就会检查是否SNAPSHOT的新版本。在这种情况下,如果不使用-o,编译将不会成功。

总结

……没有下载artifact,能不能进行离线下载?

当然不行。要想进行离线下载,本地库中必须要有所需的依赖项,让Maven下载项目所需的依赖项,最简单的办法是,运行每个Maven项目自带的“noop”命令。例如,build:start。这个命令在其它所有命令执行前执行,并且什么都不做。如果你运行build:start,Maven将会获取在project.xml文件中引用的依赖项。

使用Maven控制台(Maven Console)

如果你需要反复地从命令行运行Maven,使用Maven控制台将会帮你节省时间。Maven控制台提供了一个“shell”,你可以输入Maven的命令。使用了Maven控制台,每当你想运行Maven命令时,就不必等待虚拟机(JVM)启动。

步骤

        Maven 控制台是一个插件,你可以在命令提示符中输入maven console 来启动它。这将会产生如下的输出:

                __ __

| // |__ _Apache__ ___

| |//| / _` / V / -_) ' / ~ intelligent projects ~

|_| |_/__,_|/_//___|_||_| v. 1.0.2

The following commands are available:

list - list all available goals

help - this message

<goalname> - attain a goal

quit - quits the console

test-application 1.0 >

可以在命令行中执行的命令,都可以在这里执行。让我们试验一下。输入java:compile,Maven将执行java:compile命令,然后返回,等待下一个命令。如果要一次执行两个命令,输入的时候用空格分开即可。例如,clean test。这种方法被称为“命令连续”,有了这种方法,你可以按照顺序指定一系列你想让Maven 执行的命令。要退出Maven控制台,输入quit,要查看可用的命令,输入list。

总结

                Maven执行java:compile命令的速度非常快,不是吗?当你使用Maven控制台时,其实你是在一个已有的JAVA虚拟机(JVM)中执行Maven命令。从命令行运行Maven,每当你想运行Maven命令的时候,不得不等待JAVA虚拟机(JVM)启动。如果你不相信性能有所提高,你可以自己试一下。先从命令行连续运行10次java:compile命令,再从Maven控制台连续运行10次同样的命令。对比命令行和Maven控制台所用的时间,你会发现,JAVA虚拟机(JVM)的启动时间有所增加。如果你要反复的运行Maven命令,请使用Maven控制台,这样一来,JAVA虚拟机(JVM)只启动一次,会节省一些时间。

生成Eclipse项目

        我肯定你想在IDE(集成开发环境)中开始工作。Maven有Eclipse插件、IntelliJ IDEA插件、JBuilder插件、JDeveloper插件以及Emacs插件。Maven可以很好的与这些工具集成。本节将学习Maven与Eclipse的集成。Eclipse是一款很受欢迎的开源IDE。

步骤

        过程很简单,运行eclipse插件即可:

C:/dev/mavenbook/code/genapp/test-application> maven eclipse

build:start:

eclipse:generate-project:

[echo] Creating C:/dev/mavenbook/code/genapp/test-application/.project ...

eclipse:generate-classpath:

[echo] Creating C:/dev/mavenbook/code/genapp/test-application/.classpath ...

[echo] Contains JUnit tests

[echo] Setting compile of src/test to target/test-classes

Plugin 'cactus-maven' in project 'Test Application' is not available

[echo] Setting default output directory to target/classes

eclipse:

[echo] Now refresh your project in Eclipse (right click on the project

and select "Refresh")

BUILD SUCCESSFUL

Total time: 2 seconds

        Maven创建了两个文件:.project和.classpath,这两个文件标识这个项目为Eclipse项目。

你可以通过以下步骤将这个项目导入到Eclipse中:

1.        启动Eclipse。

2.        从菜单上选择文件(File)?导入(Import)…。

3.        选择“现有项目”,单击“下一步”按钮。

4.        在“导入”对话框中选择C:/dev/mavenbook/code/genapp/test-application目录,然后单击“完成”按钮。

接下来还有一步:把Eclipse指向本地Maven库。Eclipse使用变量-MAVEN_REPO来指向本地Maven库。你可以使用Maven来设置变量MAVEN_REPO。方法是从命令行执行如下命令:

                maven -Dmaven.eclipse.workspace=c:/eclipse/workspace eclipse:add-maven-repo

这个Maven命令用来设置位于c:/eclipse/workspace目录下的workspace中的全局变量:MAVEN_REPO。

        你也可以手工配置这个变量。步骤如下:

1.        在菜单栏上选择窗口(Window)?偏好(Reference),来打开“偏好”对话框。

2.        在左侧的树形菜单中,选择Java?编译路径(Build Path)?Classpath变量。

3.        单击“New”按钮来建立一个新的classpath变量,这时会弹出“New Variable Entry”对话框。

4.        输入变量名称MAVEN_REPO。

5.        单击“文件夹”按钮,然后选择Maven本地库。

6.        单击“OK”按钮,然后重新编译项目。

变量MAVEN_REPO只配置一次就可以了,因为这个变量是全局的,所有Eclipse项目共享这个变量。

关于IDE

……JBuilder,JDeveloper,IntelliJ IDEA

这些IDE都有一些用于Eclipse的简单插件。要为JBuilder项目生成必要的文件,运行maven jbuilder命令。对JDeveloper项目来说,运行maven jdeveloper命令;对于IntelliJ IDEA项目,运行maven idea。

获取插件和报表更详尽的列表,请访问:

.Maven插件: http://maven.apache.org/reference/plugins/index.html

.Maven的插件沙盒: http://maven.apache.org/plugins-sandbox/index.html

.SourceForge上的Maven插件: http://maven-plugins.sourceforge.net/

.第三方Maven插件:http://maven.apache.org/reference/3rdparty.html

.Matrix Maven论坛: http://www.matrix.org.cn/topic.shtml?forumId=31  

继续阅读