首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 企业软件 > 行业软件 >

Maven 札记 command

2013-12-13 
Maven 笔记 commandSubversion,现在,你只要签出源码,然后运行: mvn install 。虽然 Maven 有很多优点,包括

Maven 笔记 command




Subversion,现在,你只要签出源码,然后运行: mvn install 。虽然 Maven 有
很多优点,包括依赖管理和通过插件重用一般的构建逻辑,但它成功的最核心原因是它
定义了构建软件的一般的接口。每当你看到一个使用 Maven 的项目如 Apache Wicket
7
,你就可以假设你能签出它的源码然后使用 mvn install 构建它,没什么好争论的。


Maven 的核心其实不做什么实际的事情,除了解析一些 XML 文档,管理生命周期与插
件之外,它什么也不懂。Maven 被设计成将主要的职责委派给一组 Maven 插件,这些
插件可以影响 Maven 生命周期,提供对目标的访问。绝大多数 Maven 的动作发生于
Maven 插件的目标,如编译源码,打包二进制代码,发布站点和其它构建任务。


Maven
大部分的智能是由插件实现的,而插件从 Maven 仓库获得。事实上,第一次你用全新
的 Maven 安装运行诸如 mvn install 命令的时候,它会从中央 Maven 仓库下载大部
分核心 Maven 插件。这不仅仅是一个最小化 Maven 分发包大小的技巧,这种方式更能
让你升级插件以给你项目的构建提高能力。Maven 从远程仓库获取依赖和插件的这一事
实允许了构建逻辑的全局性重用。


Maven Surefire 插件是负责运行单元测试的插件。

项目使用 Compiler 插件进行编译,通过 Jar
插件变成 JAR 文件,还有一些插件生成报告,运行 JRuby 和 Groovy 的代码,以及一
些用来向远程服务器发布站点的插件。


Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告
诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命
周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完
成了像编译和创建一个 JAR 文件这样的工作。



描述一个Maven插件
一旦你开始使用Maven,你会花很多时间去试图获得Maven插件的信息:插件如何工
作?配置参数是什么?目标是什么? 你会经常使用help:describe 目标来获取这些信
息。通过 plugin 参数你可以指定你想要研究哪个插件,你可以传入插件的前缀(如
help 插件就是 maven-help-plugin),或者可以是 groupId:artifact[:version] ,这
里 version 是可选的。比如, 下面的命令使用 help 插件的 describe 目标来输出
Maven Help 插件的信息。
$ mvn help:describe -Dplugin=help


如果你想要 Help 插件输出完整的带有参数的目标列表,只要运行带有参数
full 的 help:describe 目标就可以了,像这样:
$ mvn help:describe -Dplugin=help -Dfull


时候你可以获取单个目标的信息,设置 mojo 参数和 plugin 参数。下面的命令列出了
Compiler 插件的 compile 目标的所有信息
$ mvn help:describe -Dplugin=compiler -Dmojo=compile -Dfull


开始一个新的Maven项目,在命令行使用Maven Archetype插件。
$ mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 \
                                         -DartifactId=simple \
                                         -DpackageName=org.sonatype.mavenbook

mvn 是Maven2的命令。archetype:create称为一个Maven目标 (goal)。如果你熟悉
Apache Ant,一个Maven目标类似于一个Ant目标 (target);它们都描述了将会在构建
中完成的工作单元 (unit of work)。

想要看这个“有效的 (effective)”POM,或者说Maven真正运行根据
的POM,在simple项目的基础目录下跑下面的命令。
$ mvn help:effective-pom
一旦你运行了此命令,你应该能看到一个大得多的POM,它暴露了Maven的默认设置


一个Maven插件是一个单个或者多个目标的集合。Maven插件的例子有一些简单但核心的
插件,像Jar插件,它包含了一组创建JAR文件的目标,Compiler插件,它包含了一组编
译源代码和测试代码的目标,或者Surefire插件,它包含一组运行单元测试和生成测试
报告的目标。而其它的,更有专门的插件包括:Hibernate3插件,用来集成流行的持久
化框架Hibernate,JRuby插件,它让你能够让运行ruby称为Maven构建的一部分或者用
Ruby来编写Maven插件。Maven也提供了自定义插件的能力。一个定制的插件可以用Java
编写,或者用一些其它的语言如Ant,Groovy,beanshell和之前提到的Ruby。


一个目标是一个明确的任务,它可以作为单独的目标运行,或者作为一个大的构
建的一部分和其它目标一起运行。一个目标是Maven中的一个“工作单元(unit of
一个简单的Maven项目
26
work)”。目标的例子包括Compiler插件中的compile目标,它用来编译项目中的所有
源文件,或者Surefire插件中的test目标,用来运行单元测试。目标通过配置属性
进行配置,以用来定制行为。例如,Compiler插件的compile目标定义了一组配置参
数,它们允许你设置目标JDK版本或者选择是否用编译优化。在之前的例子中,我们
通过命令行参数-DgroupId=org.sonatype.mavenbook.ch03和-DartifactId=simple向
Archetype插件的create目标传入了groupId和artifactId配置参数。我们也向create目
标传入了packageName参数,它的值为org.sonatype.mavenbook。如果我们忽略
了packageName参数,那么包名的默认值为org.sonatype.mavenbook.ch03。


插件目标可以附着在生命周期阶段上。随着Maven沿着生命周期的阶段移动,它会执
行附着在特定阶段上的目标。每个阶段可能绑定了零个或者多个目标。在之前的小节
一个简单的Maven项目
29
里,当你运行mvn package,你可能已经注意到了不止一个目标被执行了。检查运行mvn
package之后的输出,会注意到那些被运行的各种目标。当这个简单例子到达package阶
段的时候,它运行了Jar插件的jar目标。既然我们的简单的quickstart项目(默认)
是jar包类型,jar:jar目标被就绑定到了打包阶段。


图?3.3.?一个目标绑定到一个阶段
我们知道,在包类型为jar的项目中,打包阶段将会创建一个JAR文件。但是,在它之
前的目标做什么呢,像compiler:compile和surefire:test?在Maven经过它生命周期
中package之前的阶段的时候,这些目标被运行了;Maven执行一个阶段的时候,它首先
会有序的执行前面的所有阶段,到命令行指定的那个阶段为止。每个阶段对应了零个或
者多个目标。我们没有进行任何插件配置或者定制,所以这个例子绑定了一组标准插件
的目标到默认的生命周期。当Maven经过以package为结尾的默认生命周期的时候,下面
的目标按顺序被执行:
resources:resources
Resources插件的resources目标绑定到了resources 阶段。这个目标复制src/
main/resources下的所有资源和其它任何配置的资源目录,到输出目录。
compiler:compile
Compiler插件的compile目标绑定到了compile 阶段。这个目标编译src/main/
java下的所有源代码和其他任何配置的资源目录,到输出目录。
resources:testResources
Resources插件的testResources目标绑定到了test-resources 阶段。这个目标复
制src/test/resources下的所有资源和其它任何的配置的测试资源目录,到测试
输出目录。
compiler:testCompile
Compiler插件的testCompile目标绑定到了test-compile 阶段。这个目标编
译src/test/java下的测试用例和其它任何的配置的测试资源目录,到测试输出
目录。
surefire:test
Surefire插件的test目标绑定到了test 阶段。这个目标运行所有的测试并且创
建那些捕捉详细测试结果的输出文件。默认情况下,如果有测试失败,这个目标
会终止。
一个简单的Maven项目
30
jar:jar
Jar插件的jar目标绑定到了package 阶段。这个目标把输出目录打包成JAR文
件。

总结得来说,当我们运行mvn package,Maven运行到打包为止的所有阶段,在Maven沿
着生命周期一步步向前的过程中,它运行绑定在每个阶段上的所有目标。你也可以像下
面这样显式的指定一系列插件目标,以得到同样的结果:
mvn resources:resources \
    compiler:compile \
    resources:testResources \
    compiler:testCompile \
    surefire:test \
    jar:jar



在你的本地仓库,你应该可以看到我们的简单项目创建出来的构件。如果你运行mvn
install命令,Maven会把我们项目的构件安装到本地仓库。试一下。
$ mvn install



在你的本地仓库,你应该可以看到我们的简单项目创建出来的构件。如果你运行mvn
install命令,Maven会把我们项目的构件安装到本地仓库。试一下。
$ mvn install


就像你能从这个命令的输出看到的,Maven把我们项目的JAR文件安装到了我们的本地
Maven仓库。Maven在本地项目中通过本地仓库来共享依赖。如果你开发了两个项目——
项目A和项目B——项目B依赖于项目A产生的构件。当构建项目B的时候,Maven会从本地
一个简单的Maven项目
36
仓库取得项目A的构件。Maven仓库既是一个从远程仓库下载的构件的缓存,也允许你的
项目相互依赖


一个复杂的项目将会包含很多依赖,也有可能包含依赖于其它构件的依赖。这是Maven
最强大的特征之一,它支持了传递性依赖(transitive dependencies)。假如你
的项目依赖于一个库,而这个库又依赖于五个或者十个其它的库(就像Spring或者
Hibernate那样)。你不必找出所有这些依赖然后把它们写在你的pom.xml里,你只需
要加上你直接依赖的那些库,Maven会隐式的把这些库间接依赖的库也加入到你的项目
中。Maven也会处理这些依赖中的冲突,同时能让你自定义默认行为,或者排除一些特
定的传递性依赖。

在上图中,项目A依赖于项目B和C,项目B依赖于项目D,项目C依赖于项目E,但是项目A
所需要做的只是定义对B和C的依赖。当你的项目依赖于其它的项目,而这些项目又有一
些小的依赖时(向Hibernate, Apache Struts 或者 Spring Framework),传递性依赖使
之变得相当的方便。Maven同时也提供了一种机制,能让你排除一些你不想要的传递性
依赖。

Maven也提供了不同的依赖范围(dependency scope)。Simple项目的pom.xml包含了
一个依赖——junit:junit:jar:3.8.1——范围是test。当一个依赖的范围是test的
时候,说明它在Compiler插件运行compile目标的时候是不可用的。它只有在运
行compiler:testCompile和surefire:test目标的时候才会被加入到classpath中。

另外一个Maven的重要特征是,它能生成文档和报告。在simple项目的目录下,运行以
下命令:
$ mvn site


如果你想要运行到 test 阶段为
止的所有生命周期阶段,运行 mvn test 。


从命令行运行 mvn test 使 Maven 执行到 test 阶段为止的所有生命周期阶段。
Maven Surefire 插件有一个 test 目标,该目标被绑定在了 test 阶段。


$ mvn test -Dmaven.test.failure.ignore=true


$ mvn install -Dmaven.test.skip=true

例?4.19.?配置 Maven 装配描述符
<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
  [...]
</project>


$ cd target
$ java -cp simple-weather-1.0-jar-with-dependencies.jar org.sonatype.mavenbook.weath




创建你的 web 应用程序项目,运行 mvn archetype:create ,加上参数 artifactId
和 groupId。 指定 archetypeArtifactId 为 maven-archetype-webapp。 如此便创建了
恰到好处的目录结构和 Maven POM。
~/examples$ mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch05 \
                                                             -DartifactId=simple-web
                                                             -DpackageName=org.sonat
                                                             -DarchetypeArtifactId=




例?5.2.?配置 Jetty 插件
<project>
  [...]
  <build>
    <finalName>simple-webapp</finalName>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
  [...]
</project>



~/examples$ mvn jetty:run


在启动 Jetty 插件之前,运行 mvn compile 以编译你的项目:
~/examples$ mvn compile

在添加好这个 Servlet 规格说明依赖之后,运行 mvn clean install ,然后运行 mvn
jetty:run 。


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

一旦反应堆解决了项目构建的顺序,Maven就会在多模块构建中为每个模块执行特定的
目标。本例中,你能看到Maven在simple-webapp之前构建了simple-weather,为每个子
模块执行了mvn clean install。

~/examples/ch06/simple-parent/simple-webapp $ mvn jetty:run


在我们的build配置中,我们还配置了Maven Hibernate3插件来访问内嵌的
HSQLDB实例。要让Maven Hibernate3插件能成功的使用JDBC连接该数据库,



为了运行这个web应用,你首先需要使用Hibernate3插件构造数据库。为此,在项
目simple-webapp目录下运行如下命令:
$ mvn hibernate3:hbm2ddl


在此之后,应该有一个/usr/local/hudson/hudson-home/jobs/maven-guide-zh-to-production/workspace/content-zh/data目录包含了HSQLDB数据库。你可以使用jetty启
动web应用:
$ mvn jetty:run


simple-command项目被配置成创建一个单独的包含项目本身字节码以及所有依赖字节码
的JAR文件。要创建这个装配制品,从simple-command项目目录运行Maven Assembly插
件的assembly目标:
$ mvn assembly:assembly











热点排行