maven常见问题归纳

时间:2021-05-19 20:41:02

前言

Maven,发音是[`meivin],"专家"的意思。它是一个非常好的项目管理工具,非常早就进入了我的必备工具行列,可是这次为了把ABPM项目 全然迁移并应用maven,所以对maven进行了一些深入的学习。写这个学习笔记的目的,一个是为了自己备忘,二则希望可以为其它人学习使用maven 缩短一些时间。

maven概要

首先我把maven的概念高速的梳理一下,让我们高速地建立起一个比較精确的maven应用场景。

Maven 是一个强大的项目管理和构建自己主动化工具。它通过抽象的项目对象模型和构建生命周期模型来对项目及其构建过程进行管理。Maven 最大化的消除了构建的反复,提升了构建的效率与标准化。除此之外,Maven 还有依赖管理、自己主动生成项目网站、代码静态检查等特性。如今已经有无数开源或商业项目使用Maven进行构建,Maven 如今已经是 Java 社区事实标准的构建工具。

maven不是什么

读书时候要先限定范围,避免一些有害的遐想。要说maven不是什么。我们能够从例如以下几个要点来展开

  1. maven不是ant。也不是make。

    我们曾经接触的构建工具。须要写一些具体的步骤,比方: compile project1/src/*.java 等类似的语句。这些语句正是我们使用ant和make所要编写的东西。maven採用了"约定优于配置"的方法。一些开发经常使用的操作和步骤已经固化在 maven中,所以使用者不再须要去编写那些烦人的语句了。

    同一时候,maven内置了开发流程的支持,它不仅可以编译。相同可以打包、公布,也可以一气呵成 做完这些全部的步骤。

  2. maven不是ivy

    依赖管理是maven的功能之中的一个,尽管非常多人包含我曾经都是仅仅用它的依赖管理功能,可是要深入运用的话,我们就能够看到很多其它的内容。更重要的是。maven在依赖关系中增加了scope的概念。进一步细化了依赖关系的划分。

maven是什么

maven将自己定位为一个项目管理工具。它负责管理项目开发过程中的差点儿全部的东西:

  1. 版本号

    maven有自己的版本号定义和规则
  2. 构建

    maven支持很多种的应用程序类型。对于每一种支持的应用程序类型都定义好了一组构建规则和工具集。
  3. 输出物管理

    maven能够管理项目构建的产物,并将其增加到用户库中。这个功能能够用于项目组和其它部门之间的交付行为。
  4. 依赖关系

    maven对依赖关系的特性进行仔细的分析和划分,避免开发过程中的依赖混乱和相互污染行为
  5. 文档和构建结果

    maven的site命令支持各种文档信息的公布,包含构建过程的各种输出,javadoc,产品文档等。
  6. 项目关系

    一个大型的项目通常有几个小项目或者模块组成,用maven能够非常方便地管理
  7. 移植性管理

    maven能够针对不同的开发场景,输出不同种类的输出结果。

maven的生命周期

maven把项目的构建划分为不同的生命周期(lifecycle),在我看来,划分的已经是很细致了。大家能够參考这里 。

粗略一点的话,它这个过程(phase)包含:编译、測试、打包、集成測试、验证、部署

maven中全部的运行动作(goal)都须要指明自己在这个过程中的运行位置,然后maven运行的时候,就按照过程的发展依次调用这些goal进行各种处理。

这个也是maven的一个基本调度机制。一般来说。位置稍后的过程都会依赖于之前的过程。

当然,maven相同提供了配置文件,能够按照用户要求,跳过某些阶段。

maven的"约定优于配置"

所谓的"约定优于配置",在maven中并非全然不能够改动的,他们仅仅是一些配置的默认值而已。

可是使用者除非必要,并不须要去改动那些约定内容。

maven默认的文件存放结构例如以下:

  • /项目文件夹
    • pom.xml 用于maven的配置文件
    • /src 源码文件夹
      • /src/main project源码文件夹
        • /src/main/java projectjava源码文件夹
      • /src/main/resource project的资源文件夹
      • /src/test 单元測试文件夹
        • /src/test/java
    • /target 输出文件夹。全部的输出物都存放在这个文件夹下
      • /target/classes 编译之后的class文件

每个阶段的任务都知道怎么正确完毕自己的工作。比方compile任务就知道从src/main/java下编译全部的java文件,并把它的输出class文件存放到target/classes中。

对maven来说,採用"约定优于配置"的策略能够降低改动配置的工作量。也能够降低学习成本。更重要的是。给项目引入了统一的规范。

maven的版本号规范

maven使用例如以下几个要素来唯一定位某一个输出物: groupId:artifactId:packaging:version 。比方org.springframework:spring:2.5 。每一个部分的解释例如以下:

  • groupId

    团体,公司。小组,组织,项目,或者其他团体。

    团体标识的约定是,它以创建这个项目的组织名称的逆向域名(reverse domain name)开头。来自Sonatype的项目有一个以com.sonatype开头的groupId,而Apache Software的项目有以org.apache开头的groupId。

  • artifactId

    在groupId下的表示一个单独项目的唯一标识符。

    比方我们的tomcat, commons等。不要在artifactId中包括点号(.)。

  • version

    一个项目的特定版本号。公布的项目有一个固定的版本号标识来指向该项目的某一个特定的版本号。

    而正在开发中的项目能够用一个特殊的标识。这样的标识给版本号加上一个"SNAPSHOT"的标记。

    尽管项目的打包格式也是Maven坐标的重要组成部分,可是它不是项目唯一标识符的一个部分。一个项目的 groupId:artifactId:version使之成为一个独一无二的项目;你不能同一时候有一个拥有相同的groupId, artifactId和version标识的项目。

  • packaging

    项目的类型,默认是jar。描写叙述了项目打包后的输出。

    类型为jar的项目产生一个JAR文件。类型为war的项目产生一个web应用。

  • classifier

    非常少使用的坐标,一般都能够忽略classifiers。

    假设你要公布相同的代码,可是因为技术原因须要生成两个单独的构件,你就要使用一个分类器 (classifier)。比如。假设你想要构建两个单独的构件成JAR。一个使用Java 1.4编译器。还有一个使用Java 6编译器,你就能够使用分类器来生成两个单独的JAR构件,它们有相同的groupId:artifactId:version组合。假设你的项目使用本 地扩展类库,你能够使用分类器为每个目标平台生成一个构件。分类器经常使用于打包构件的源代码,JavaDoc或者二进制集合。

maven有自己的版本号规范,通常是例如以下定义 <major version>.<minor version>.<incremental version>-<qualifier> , 比方1.2.3-beta-01。要说明的是,maven自己推断版本号的算法是major,minor,incremental部分用数字比 较,qualifier部分用字符串比較。所以要小心 alpha-2和alpha-15的比較关系,最好用 alpha-02的格式。

maven在版本号管理时候能够使用几个特殊的字符串 SNAPSHOT ,LATEST ,RELEASE 。比方"1.0-SNAPSHOT"。

各个部分的含义和处理逻辑例如以下说明:

  • SNAPSHOT

    假设一个版本号包括字符串"SNAPSHOT",Maven就会在安装或公布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC时间。例 如,"1.0-SNAPSHOT"会在2010年5月5日下午2点10分公布时候变成1.0-20100505-141000-1。

    这个词仅仅能用于开发过程中,由于一般来说。项目组都会频繁公布一些版本号,最后实际公布的时候。会在这些snapshot版本号中寻找一个稳定的,用于正式发 布,比方1.4版本号公布之前,就会有一系列的1.4-SNAPSHOT,而实际公布的1.4,也是从中拿出来的一个稳定版。
  • LATEST

    指某个特定构件的最新公布,这个公布可能是一个公布版,也可能是一个snapshot版。详细看哪个时间最后。
  • RELEASE

    指最后一个公布版。

maven的组成部分

maven把整个maven管理的项目分为几个部分,一个部分是源码。包含源码本身、相关的各种资源,一个部分则是单元測试用例。另外一部分则是各种maven的插件。对于这几个部分,maven能够独立管理他们。包含各种外部依赖关系。

maven的依赖管理

依赖管理通常是最吸引人使用maven的功能特性了。这个特性让开发人员仅仅须要关注代码的直接依赖,比方我们用了spring。就增加spring依赖说明就能够了,至于spring自己还依赖哪些外部的东西。maven帮我们搞定。

随意一个外部依赖说明包括例如以下几个要素:groupId, artifactId, version, scope, type, optional。

当中前3个是必须的,各自含义例如以下:

  • groupId 必须
  • artifactId 必须
  • version 必须。

    这里的version能够用区间表达式来表示,比方(2.0,)表示>2.0。[2.0,3.0)表示2.0<=ver<3.0;多个条件之间用逗号分隔,比方[1,3),[5,7]。
  • scope 作用域限制
  • type 一般在pom引用依赖时候出现,其它时候不用
  • optional 是否可选依赖

maven觉得,程序对外部的依赖会随着程序的所处阶段和应用场景而变化。所以maven中的依赖关系有作用域(scope)的限制。在maven中,scope包括例如以下的取值:

  • compile(编译范围)

    compile是默认的范围;假设没有提供一个范围。那该依赖的范围就是编译范围。编译范围依赖在全部的classpath中可用,同一时候它们也会被打包。
  • provided(已提供范围)

    provided依赖仅仅有在当JDK或者一个容器已提供该依赖之后才使用。比如,假设你开发了一个web应用,你可能在编译classpath中须要可用 的Servlet API来编译一个servlet。可是你不会想要在打包好的WAR中包括这个Servlet API;这个Servlet API JAR由你的应用server或者servlet容器提供。已提供范围的依赖在编译classpath(不是执行时)可用。它们不是传递性的,也不会被打包。
  • runtime(执行时范围)

    runtime依赖在执行和測试系统的时候须要,但在编译的时候不须要。比方,你可能在编译的时候仅仅须要JDBC API JAR,而仅仅有在执行的时候才须要JDBC驱动实现。
  • test(測试范围)

    test范围依赖 在一般的 编译和执行时都不须要,它们仅仅有在測试编译和測试执行阶段可用。測试范围依赖在之前的?

    ??中介绍过。

  • system(系统范围)

    system范围依赖与provided类似,可是你必须显式的提供一个对于本地系统中JAR文件的路径。

    这么做是为了同意基于本地对象编译。而这些对象是系统类库的一部分。

    这种构件应该是一直可用的。Maven也不会在仓库中去寻找它。 假设你将一个依赖范围设置成系统范围。你必须同一时候提供一个systemPath元素 。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的Maven仓库中引用依赖)。

另外,代码有代码自己的依赖。各个maven使用的插件也能够有自己的依赖关系。依赖也能够是可选的。比方我们代码中没有不论什么cache依赖,可是hibernate可能要配置cache。所以该cache的依赖就是可选的。

多项目管理

maven的多项目管理也是很强大的。

一般来说,maven要求同一个project的全部子项目都放置到同一个文件夹下,每个子文件夹代表一个项目。比方

  • 总项目/
    • pom.xml 总项目的pom配置文件
    • 子项目1/
      • pom.xml 子项目1的pom文件
    • 子项目2/
      • pom.xml 子项目2的pom文件

依照这样的格式存放,就是继承方式,全部详细子项目的pom.xml都会继承总项目pom的内容。取值为子项目pom内容优先。

要设置继承方式。首先要在总项目的pom中增加例如以下配置

<modules>
<module>simple-weather</module>
<module>simple-webapp</module>
</modules>

其次在每一个子项目中增加

<parent>
<groupId>org.sonatype.mavenbook.ch06</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>  

就可以。

当然,继承不是唯一的配置文件共用方式。maven还支持引用方式。引用pom的方式更简单。在依赖中增加一个type为pom的依赖就可以。

<project>
<description>This is a project requiring JDBC</description>
...
<dependencies>
...
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>

属性

用户能够在maven中定义一些属性,然后在其它地方用${xxx}进行引用。

比方:

<project>
<modelVersion>4.0.0</modelVersion>
...
<properties>
<var1>value1</var1>
</properties>
</project>

maven提供了三个隐式的变量。用来訪问系统环境变量、POM信息和maven的settings:

  • env

    暴露操作系统的环境变量。比方env.PATH
  • project

    暴露POM中的内容。用点号(.)的路径来引用POM元素的值。比方${project.artifactId}。另外。java的系统属性比方user.dir等,也暴露在这里。
  • settings

    暴露maven的settings的信息。也能够用点号(.)来引用。maven把系统配置文件存放在maven的安装文件夹中,把用户相关的配置文件存放 在~/.m2/settings.xml(unix)或者%USERPROFILE%/.m2/settings.xml(windows)中。

maven的profile

profile是maven的一个重要特性。它能够让maven能够自己主动适应外部的环境变化。比方同一个项目。在linux下编译linux的版 本,在win下编译win的版本号等。

一个项目能够设置多个profile。也能够在同一时间设置多个profile被激活(active)的。自己主动激活的 profile的条件能够是各种各样的设定条件。组合放置在activation节点中,也能够通过命令行直接指定。

profile包括的其它配置内容可 以覆盖掉pom定义的对应值。假设觉得profile设置比較复杂,能够将全部的profiles内容移动到专门的 profiles.xml 文件里,只是记得和pom.xml放在一起。

activation节点中的激活条件中常见的有例如以下几个:

1、OS

推断操作系统相关的參数,它包括例如以下能够*组合的子节点元素

    • message - 规则失败之后显示的消息
    • arch - 匹配cpu结构,常见为x86
    • family - 匹配操作系统家族。常见的取值为:dos。mac,netware,os/2,unix。windows,win9x,os/400等
    • name - 匹配操作系统的名字
    • version - 匹配的操作系统版本
    • display - 检測到操作系统之后显示的信息
  1. <profiles>
    <profile>
    <id>profileTest1</id>
    <activation>
    <os>
    <name>Windows XP</name>
    <family>Windows</family>
    <arch>x86</arch>
    <version>5.1.2600</version>
    </os>
    </activation>
    </profile>
    </profiles>

    上面的情况就是依据操作系统的类型来激活profileTest1。

  2. 2、jdk
  3. 检查jdk版本号,能够用区间表示。
  4. <profiles>
    <profile>
    <id>profileTest1</id>
    <jdk>1.5</jdk>
    </profile>
    <profiles>

    上面情况表示在jdk为1.5版本号系列的时候激活profileTest1。

    <profiles>
    <profile>
    <id>profileTest1</id>
    <jdk>[1.4,1.7)</jdk>
    </profile>
    <profiles>

    上面的情况表示在jdk为1.4、1.5和1.6的时候激活profileTest1。



    3、property

     检查属性值,本节点能够包括name和value两个子节点。
    <profiles>
    <profile>
    <id>profileTest1</id>
    <activation>
    <property>
    <name>hello</name>
    <value>world</value>
    </property>
    </activation>
    </profile>
    </profiles>

    上面的profileTest1将在提供了系统属性hello,而且其值为world的时候激活。以下的做法能够激活profileTest1。

    mvn package –Dhello=world 

    4、file

    检查文件相关内容。包括两个子节点:exists和missing。用于分别检查文件存在和不存在两种情况。
    <profiles>
    <profile>
    <id>profileTest1</id>
    <activation>
    <file>
    <exists>target</exists>
    </file>
    </activation>
    </profile>
    </profiles>

    上面的定义表示当存在target文件时激活profileTest1。


    maven的操作和使用

    maven的操作有两种方式,一种是通过mvn命令行命令,一种是使用maven的eclipse插件。由于使用eclipse的maven插件操作起来比較easy,这里就仅仅介绍使用mvn命令行的操作。

    maven的配置文件

    maven的主执行程序为mvn.bat。linux下为mvn.sh,这两个程序都非常easy。它们的共同用途就是收集一些參数,然后用 java.exe来执行maven的Main函数。

    maven相同须要有配置文件,名字叫做settings.xml,它放在两个地方,一个是maven 安装文件夹的conf文件夹下,对全部使用该maven的用户都起作用,我们称为主配置文件。另外一个放在 %USERPROFILE%/.m2/settings.xml下,我们成为用户配置文件。仅仅对当前用户有效,且能够覆盖主配置文件的參数内容。

    还有就是
    项目级别的配置信息了,它存放在每个maven管理的项目文件夹下,叫pom.xml。主要用于配置项目相关的一些内容。当然,假设有必要,用户也能够在 pom中写一些配置,覆盖住配置文件和用户配置文件的设置參数内容。

    一般来说,settings文件配置的是比方repository库路径之类的全局信息。详细能够參考官方站点的文章 。

    创建新project

    要创建一个新的mavenproject。我们须要给我们的project指定几个必要的要素,就是maven产品坐标的几个要素:groupId, artifactId,假设愿意。你也能够指定version和package名称。我们先看一个简单的创建命令:

    d:\work\temp>mvn archetype:create -DgroupId=com.abc -DartifactId=product1 -DarchetypeArtifactId=maven-archetype-webapp

    首先看这里的命令行參数的传递结构。怪异的 -D參数=值 的方式是 java.exe 要求的方式。这个命令创建一个webproject。文件夹结构是一个标准的maven结构,例如以下:

    D:.
    └─mywebapp
    │ pom.xml

    └─src
    └─main
    ├─resources
    └─webapp
    │ index.jsp

    └─WEB-INF
    web.xml

    大家要注意,这里文件夹结构的布局实际上是由參数 archetypeArtifactId 来决定的,由于这里传入的是 maven-archetype-webapp假设我们传入其它的就会创建不同的结构。默认值为 maven-archetype-quickstart ,有兴趣的读者能够參考更具体的列表 ,我把部分经常使用的列表在这里:

    Artifact Group Version Repository Description

    maven-archetype-j2ee-simple org.apache.maven.archetypes

    A simple J2EE Java application
    maven-archetype-marmalade-mojo org.apache.maven.archetypes

    A Maven plugin development project using marmalade
    maven-archetype-plugin org.apache.maven.archetypes

    A Maven Java plugin development project
    maven-archetype-portlet org.apache.maven.archetypes

    A simple portlet application
    maven-archetype-profiles org.apache.maven.archetypes


    maven-archetype-quickstart org.apache.maven.archetypes


    maven-archetype-simple org.apache.maven.archetypes


    maven-archetype-site-simple org.apache.maven.archetypes

    A simple site generation project
    maven-archetype-site org.apache.maven.archetypes

    A more complex site project
    maven-archetype-webapp org.apache.maven.archetypes

    A simple Java web application
    maven-archetype-har net.sf.maven-har 0.9
    Hibernate Archive
    maven-archetype-sar net.sf.maven-sar 0.9
    JBoss Service Archive

    大家能够參考更具体的 archetype:create 帮助 和 archtype參考信息 。

    maven的多项目管理

    多项目管理是maven的主要特色之中的一个。对于一个大型project,用maven来管理他们之间复杂的依赖关系,是再好只是了。maven的项目配置之间的关系有两种:继承关系和引用关系。

    maven默认依据文件夹结构来设定pom的继承关系。即下级文件夹的pom默认继承上级文件夹的pom。要设定两者之间的关系非常easy。上级pom例如以下设置:

    <modules>
    <module>ABCCommon</module>
    <module>ABCCore</module>
    <module>ABCTools</module>
    </modules>

    要记住的是。这里的module是文件夹名,不是子project的artifactId。

    子project例如以下设置:

    <parent>
    <groupId>com.abc.product1</groupId>
    <artifactId>abc-product1</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>abc-my-module2</artifactId>
    <packaging>jar</packaging>

    这样两者就相互关联起来了,继承关系就设定完成,全部父project的配置内容都会自己主动在子project中生效,除非子project有同样的配置覆盖。假设你不喜欢层层递进的文件夹结构来实现继承,也能够在parent中增加 <relativePath>../a-parent/pom.xml</relativePath> 来制定parent项目的相对文件夹。继承关系通经常使用在项目共同特性的抽取上,通过抽取公共特性。能够大幅度降低子项目的配置工作量。

    引用关系是第二种复用的方式,maven中配置引用关系也非常easy,增加一个 type 为 pom 的依赖就可以。

    <dependency>
    <groupId>org.sonatype.mavenbook</groupId>
    <artifactId>persistence-deps</artifactId>
    <version>1.0</version>
    <type>pom</type>
    </dependency>

    可是不管是父项目还是引用项目,这些project都必须用 mvn install 或者 mvn deploy 安装到本地库才行,否则会报告依赖没有找到。eclipse编译时候也会出错。

    须要特别提出的是复用过程中。父项目的pom中能够定义 dependencyManagement 节点。当中存放依赖关系,可是这个依赖关系仅仅是定义,不会真的产生效果。假设子项目想要使用这个依赖关系,能够在本身的 dependency 中加入一个简化的引用

    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring</artifactId>
    </dependency>

    这样的方法能够避免版本满天飞的情况。

    安装库文件到maven库中

    在maven中一般都会用到安装库文件的功能,一则是我们经常使用的hibernate要使用jmx库。可是由于sun的license限制,所以无法将其直接包括在repository中。

    所以我们使用mvn命令把jar安装到我们本地的repository中

    mvn install:install-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file

    假设我们想把它安装到公司的repository中。须要使用命令

    mvn deploy:deploy-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file -Durl=http://aaa.ss.com/ss.xxx -DrepositoryId=release-repo

    对于我们的project输出,假设须要放置到公司的repository中的话,能够通过配置pom来实现

    <distributionManagement>
    <repository>
    <id>mycompany-repository</id>
    <name>MyCompany Repository</name>
    <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
    </distributionManagement>

    这里使用的scp方式提交库文件。还有其它方式能够使用,请參考faq部分。然后记得在你的settings.xml中增加这一内容

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    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>mycompany-repository</id>
    <username>jvanzyl</username>
    <!-- Default value is ~/.ssh/id_dsa -->
    <privateKey>/path/to/identity</privateKey>
    <passphrase>my_key_passphrase</passphrase>
    </server>
    </servers>
    ...
    </settings>

    maven的变量

    maven定义了非常多变量属性,參考这里 http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

    1. 内置属性
      • ${basedir } 项目根文件夹
      • ${version } 等同于 ${project.version } or ${pom.version }
    2. Pom/Project properties

      全部pom中的元素都能够用 project. 前缀进行引用,下面是部分经常使用的
      • ${project.build.directory } 构建文件夹,缺省为target
      • ${project.build.outputDirectory} 构建过程输出文件夹。缺省为target/classes
      • ${project.name } refers to the name of the project.
      • ${project.version } refers to the version of the project.
      • ${project.packaging} 打包类型。缺省为jar
      • ${project.xxx} 当前pom文件的随意节点的内容
      • ${project.build.finalName } 产出物名称,缺省为${project.artifactId}-${project.version}
    3. 本地用户设定

      全部用的的 settings.xml 中的设定都能够通过 settings. 前缀进行引用
      • ${settings.localRepository } refers to the path of the user's local repository.
      • ${maven.repo.local } also works for backward compatibility with maven1 ??
    4. 环境变量

      系统的环境变量通过 env. 前缀引用
      • ${env.M2_HOME } returns the Maven2 installation path.
      • ${java.home } specifies the path to the current JRE_HOME environment use with relative paths to get for example:

        <jvm>${java.home}../bin/java.exe</jvm>
    5. java系统属性

      全部JVM中定义的java系统属性.
    6. 用户在pom中定义的自己定义属性
      <project>
      ...
      <properties>
      <my.filter.value>hello</my.filter.value>
      </properties>
      ...
      </project>
      • ${my.filter.value } will result in hello if you inserted the above XML fragment in your pom.xml
    7. 上级project的变量

      上级project的pom中的变量用前缀 ${project.parent } 引用. 上级project的版本号也能够这样引用: ${parent.version }

    maven的使用

    我们已经知道maven提前定义了很多的阶段(phase)。每一个插件都依附于这些阶段。而且在进入某个阶段的时候,调用执行这些相关插件的功能。我们先来看完整的maven生命周期:

    生命周期 阶段描写叙述

    validate 验证项目是否正确,以及全部为了完整构建必要的信息是否可用
    generate-sources 生成全部须要包括在编译过程中的源码
    process-sources 处理源码,比方过滤一些值
    generate-resources 生成全部须要包括在打包过程中的资源文件
    process-resources 复制并处理资源文件至目标文件夹,准备打包
    compile 编译项目的源码
    process-classes 后处理编译生成的文件,比如对Java类进行字节码增强(bytecode enhancement)
    generate-test-sources 生成全部包括在測试编译过程中的測试源代码
    process-test-sources 处理測试源代码,比方过滤一些值
    generate-test-resources 生成測试须要的资源文件
    process-test-resources 复制并处理測试资源文件至測试目标文件夹
    test-compile 编译測试源代码至測试目标文件夹
    test 使用合适的单元測试框架执行測试。这些測试应该不须要代码被打包或公布
    prepare-package 在真正的打包之前,运行一些准备打包必要的操作。这一般会产生一个包的展开的处理过的版本号(将会在Maven 2.1+中实现)
    package 将编译好的代码打包成可分发的格式,如JAR,WAR。或者EAR
    pre-integration-test 执行一些在集成測试执行之前须要的动作。如建立集成測试须要的环境
    integration-test 假设有必要的话,处理包并公布至集成測试能够执行的环境
    post-integration-test 执行一些在集成測试执行之后须要的动作。如清理集成測试环境。
    verify 运行全部检查。验证包是有效的,符合质量规范
    install 安装包至本地仓库,以备本地的其他项目作为依赖使用
    deploy 复制终于的包至远程仓库,共享给其他开发者和项目(通常和一次正式的公布相关)

    maven核心的插件列表能够參考 http://maven.apache.org/plugins/index.html 。

    这里仅列举几个经常使用的插件及其配置參数:

    1. clean插件 

      仅仅包括一个goal叫做 clean:clean ,负责清理构建时候创建的文件。 默认清理的位置是例如以下几个变量指定的路径project.build.directory, project.build.outputDirectory, project.build.testOutputDirectory, and project.reporting.outputDirectory 。
    2. compiler插件 

      包括2个goal,各自是 compiler:compile 和 compiler:testCompile 。能够到这里查看两者的详细參数设置:compile ,testCompile 。
    3. surefire插件 

      执行单元測试用例的插件,而且可以生成报表。包括一个goal为 surefire:test 。主要參数testSourceDirectory用来指定測试用例文件夹,參考完整使用方法帮助
    4. jar 

      负责将project输出打包到jar文件里。包括两个goal,各自是 jar:jar , jar:test-jar 。

      两个goal负责从classesDirectory或testClassesDirectory中获取全部资源。然后输出jar文件到outputDirectory中。

    5. war 

      负责打包成war文件。经常使用goal有 war:war 。负责从warSourceDirectory(默认${basedir}/src/main/webapp)打包全部资源到outputDirectory中。
    6. resources 

      负责复制各种资源文件。经常使用goal有 resources:resources 。负责将资源文件拷贝到outputDirectory中,默觉得${project.build.outputDirectory}。
    7. install 

      负责将项目输出(install:install)或者某个指定的文件(install:install-file)增加到本机库%USERPROFILE%/.m2/repository中。

      能够用 install:help 寻求帮助。

    8. deploy 

      负责将项目输出(deploy:deploy)或者某个指定的文件(deploy:deploy-file)增加到公司库中。
    9. site 

      将project全部文档生成站点,生成的站点界面默认和apache的项目站点类似,可是其文档用doxia格式写的,眼下不支持docbook。须要用其它插件配合才干支持。
    依赖关系
    怎样添加删除一个依赖关系?问:怎样添加删除一个依赖关系?

    答:直接在pom文件里增加一个dependency节点,假设要删除依赖。把相应的dependency节点删除就可以。

    问:怎样屏蔽一个依赖关系?比方项目中使用的libA依赖某个库的1.0版。libB以来某个库的2.0版,如今想统一使用2.0版,怎样去掉1.0版的依赖?

    答:设置exclusion就可以。

    <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate</artifactId>
    <version>3.2.5.ga</version>
    <exclusions>
    <exclusion>
    <groupId>javax.transaction</groupId>
    <artifactId>jta</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
    问:我有一些jar文件要依赖,可是我又不想把这些jar去install到mvn的repository中去。怎么做配置?

    答:增加一个特殊的依赖关系,使用system类型。例如以下:

    <dependency>
    <groupId>com.abc</groupId>
    <artifactId>my-tools</artifactId>
    <version>2.5.0</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>${basedir}/lib/mylib1.jar</systemPath>
    </dependency>

    可是要记住,公布的时候不会复制这个jar。须要手工配置,并且其它project依赖这个project的时候,会报告警告。假设没有特殊要求,建议直接注冊公布到repository。

    问:在eclipse环境中同一时候使用maven
    builder和eclipse builder,而且设置项目依赖关系之后。为什么编译会出现artifact找不到错误,可是直接使用命令行mvn构建则一切正常?

    答:在project属性中去掉java build path中对其它 project 的依赖关系,直接在pom中设置依赖关系就可以

    <!-- 依赖的其它项目 -->
    <dependency>
    <groupId>com.abc.project1</groupId>
    <artifactId>abc-project1-common</artifactId>
    <version>${project.version}</version>
    </dependency>

    另外。保证没有其它错误。

    问:我想让输出的jar包自己主动包括全部的依赖

    答:使用 assembly 插件就可以。

    <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
    <descriptorRefs>
    <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
    </configuration>
    </plugin>
    问:我的測试用例依赖于其它project的測试用例,怎样设置?

    答:maven本身在公布的时候,能够公布单纯的jar,也能够同一时候公布xxx-tests.jar和xxx-javadoc.jar(大家常常在repository中能够看到类似的东西)。我们自己的项目A要同一时候输出test.jar能够做例如以下的设置

    <!-- 用于把test代码也做成一个jar -->
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>test-jar</goal>
    </goals>
    </execution>
    </executions>
    </plugin>

    然后在其它须要引用的projectB中做例如以下的dependency设置

    <dependency>
    <groupId>com.abc.XXX</groupId>
    <artifactId>工程A</artifactId>
    <version>${project.version}</version>
    <type>test-jar</type>
    <scope>test</scope>
    </dependency>

    变量

    问:怎样使用变量替换?项目中的某个配置文件比方jdbc.properties使用了一些pom中的变量,怎样在公布中使用包括真实内容的终于结果文件?

    答:使用资源过滤功能,比方:

    <project>
    ..
    <properties>
    <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
    <jdbc.url>jdbc:mysql://localhost:3306/development_db</jdbc.url>
    <jdbc.username>dev_user</jdbc.username>
    <jdbc.password>s3cr3tw0rd</jdbc.password>
    </properties>
    ..
    <build>
    <resources>
    <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
    </resource>
    </resources>
    </build>
    ..
    <profiles>
    <profile>
    <id>production</id>
    <properties>
    <jdbc.driverClassName>oracle.jdbc.driver.OracleDriver</jdbc.driverClassName>
    <jdbc.url>jdbc:oracle:thin:@proddb01:1521:PROD</jdbc.url>
    <jdbc.username>prod_user</jdbc.username>
    <jdbc.password>s00p3rs3cr3t</jdbc.password>
    </properties>
    </profile>
    </profiles>
    </project>
    问: maven-svn-revision-number-plugin 插件说明

    答: maven-svn-revision-number-plugin 能够从 SVN 中获取版本,并将其变成环境变量,交由其它插件或者profile使用。具体帮助在这里 。

    一般和resource的filter机制同一时候使用

    <plugins>
    <plugin>
    <groupId>com.google.code.maven-svn-revision-number-plugin</groupId>
    <artifactId>maven-svn-revision-number-plugin</artifactId>
    <version>1.3</version>
    <executions>
    <execution>
    <goals>
    <goal>revision</goal>
    </goals>
    </execution>
    </executions>
    <configuration>
    <entries>
    <entry>
    <prefix>prefix</prefix>
    </entry>
    </entries>
    </configuration>
    </plugin>
    </plugins>

    这段代码负责把resource文件里的内容替换成适当内容

    repository = ${prefix.repository}
    path = ${prefix.path}
    revision = ${prefix.revision}
    mixedRevisions = ${prefix.mixedRevisions}
    committedRevision = ${prefix.committedRevision}
    status = ${prefix.status}
    specialStatus = ${prefix.specialStatus}

    编译

    问:怎样给插件指派參数?比方我要设置一些编译參数

    答:下面内容设定编译器编译java1.5的代码

    <project>
    ...
    <build>
    ...
    <plugins>
    <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
    <source>1.5</source>
    <target>1.5</target>
    </configuration>
    </plugin>
    </plugins>
    ...
    </build>
    ...
    </project>

    要设置其它插件的參数也能够,请參考相应插件的帮助信息

    问:我的文件夹是非标准的文件夹结构。怎样设置让maven支持?

    答:指定source文件夹和test-source文件夹就可以。

    <build>
    <directory>target</directory>
    <sourceDirectory>src</sourceDirectory>
    <scriptSourceDirectory>js/scripts</scriptSourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>
    <outputDirectory>bin</outputDirectory>
    <testOutputDirectory>bin</testOutputDirectory>
    </build>

    这个样例把源码设置成了src文件夹。測试代码在test文件夹,所以输出到bin文件夹。这里要注意,directory假设也设置成bin文件夹的 话,maven打包的时候会引起死循环,由于directory是全部工作存放的地方,默认包括outputDirectory定义的文件夹在内。