Maven技术解析

Maven简单介绍

Maven是一个项目管理工具。强大,但是很容易使用。

它包含了:

  • 一个项目对象模型 (Project Object Model);
  • 一组标准集合;
  • 一个项目生命周期(Project Lifecycle);
  • 一个依赖管理系统(Dependency Management System);
  • 用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后 Maven 可以应用横切的逻辑, 这些逻辑来自一组共享的(或者自定义的)插件。

如果看完简介,你还迷糊的,那么我想说:这很正常!请心无旁骛地往下看,学习完这个入门教程,该懂的你就都懂了。


温馨提示:本文的最后一个主题是个动手示例,如果大段的文字定义让你非常没有效率,那么,你可以在任何时候先来动手完成这个示例。找找感觉,然后再来看这些枯燥的定义。

安装Maven

在Mac OSX上安装Maven

你可以从http://maven.apache.org/download.html下载Maven的二进制版本。下载最新 的,下载格式最方便你使用的版本。找个地方存放它,并把存档文件解开。如果你把存 档文件解压到 /usr/local/maven-2.0.9 ;你可能会需要创建一个符号链接,那样就能更容易使用,当你升级Maven的时候也不再需要改变环境变量。
/usr/local % ln -s maven-2.0.9 maven /usr/local % export M2_HOME=/usr/local/maven /usr/local % export PATH=/usr/local/maven/bin:/usr/local/bin:/usr/local/maven/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/java/latest/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/usr/local/bin
将Maven安装好后,你还需要做一些事情以确保它正确工作。你需要将它的 bin 目录 (该例中为 /usr/local/maven/bin)添加到你的命令行路径下。你还需要设置 M2_HOME 环境变量,其对应值为Maven的根目录(该例中为 /usr/local/maven)。
注意
在OSX Tiger和OSX Leopard上安装指令是相同的。有报告称Maven 2.0.6正 和XCode的预览版本一起发布。如果你安装了XCode,从命令行运行 mvn 检 查一下它是否可用。 XCode把Maven安装在了/usr/share/maven。我们强烈建 议安装最新版本的Maven 2.0.9,因为随着Maven 2.0.9的发布很多bug被修 正了,还有很多改进。
你还需要把 M2_HOME 和 PATH 写到一个脚本里,每次登陆的时候运行这个脚本。把下 面的几行加入到 .bash_login。
export M2_HOME=/usr/local/maven export PATH=/usr/local/maven/bin:/usr/local/bin:/usr/local/maven/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/java/latest/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/usr/local/bin
一旦你把这几行加入到你的环境中,你就可以在命令行运行Maven了。
注意
这些安装指令假设你正运行bash。

在Microsoft Windows上安装Maven

在Windows上安装Maven和在Mac OSX上安装Maven十分类似,最主要的区别在于安装位置和设置环境变量。在这里假设Maven安装目录是 c:\Program Files\maven-2.0.9 ,但 是,只要你设置的正确的环境变量,把Maven安装到其它目录也一样。当你把Maven解 压到安装目录后,你需要设置两个环境变量——PATH和M2_M2_HOME。设置这两个环境变量,键入下面的命令:
C:\Users\tobrien > set M2_HOME=c:\Program Files\maven-2.0.9
C:\Users\tobrien > set PATH=%PATH%;%M2_HOME%\bin

在命令行设置环境变量后,你可以在当前会话使用Maven,但是,除非你通过控制面 板把它们加入系统变量,你将需要每次登陆系统的时候运行这两行命令。你应该在 Microsoft Windows中通过控制面板修改这两个变量。

在Linux上安装Maven

遵循第 2.3.1 节 “在Mac OSX上安装Maven”的步骤,在Linux机器上安装Maven。

扫清障碍

学习新技能的时候,有太多的内容需要去探索,快速有效的获取信息非常重要。掌握下边两个方法,可以助你快速掌握maven。

help 插件的使用方法

tags:maven help

目的:使用help插件,配合不同的参数,查看maven插件的相关信息。

  • 命令:mvn help:describe -Dplugin=插件名称mvn 插件名称:help
    作用:查看插件的描述信息。

  • 命令:mvn help:describe -Dplugin=插件名称 -Dmojo=目标名称
    作用:查看插件的某个【目标】的简介信息。

  • 命令:mvn help:describe -Dplugin=插件名称 -Dmojo=目标名称 -Ddetail
    或者这么写 mvn 插件名称:help -Ddetail=true -Dgoal=目标名称
    作用:查看help插件的某个【目标】的详细信息。

maven自有参数

使用 mvn --help 命令查看maven自有参数信息,比如-D、-X、-e


Maven核心概念

约定大于配置

在必要的情况下才进行自定义,否则使用maven默认设置。


插件(plugin), 目标(goal)参数生命周期生命周期阶段

插件

是一组【目标】的集合。maven使用插件来完成特定的任务。

比如:创建项目使用archetype插件,编译项目使用compiler插件,使用install插件编译、测试、打包项目并安装到本地库中等。
注意install插件,他同时也是一个maven生命周期阶段,因为在执行install时,它使用了多个插件,完成了多个目标。

先记下,后边再说。


目标(goal)

  • 被用来完成明确的任务。
  • 它可以作为单独的目标运行,也可以作为一个大的构建的一部分和其它目标一起运行。
  • 一个目标是Maven中的一个“工作单元(unit of work)“。

你会在maven的输出中经常看到一个词:Mojo。mojo就是goal。A Maven plain Old Java Object.

示例:

help是一个maven插件。它包括9个目标。

help:active-profiles
help:all-profiles
help:describe
help:effective-pom
help:effective-settings
help:evaluate
help:expressions
help:help
help:system
  • 使用命令 mvn 插件名称:help 查看插件的目标。

参数

目标定义了一些参数,可以在执行目标时,向目标传递参数值来达成个性化的结果。

  • 使用命令 mvn help:describe -Dplugin=插件名称 -Dmojo=目标名称 -Ddetail 查看目标的参数。

生命周期

生命周期就是一个项目从无到有的整个过程,这个过程里包含了多个阶段(比如创建、编译、测试、打包/构建、部署),每个阶段就叫做生命周期阶段。Maven的生命周期是抽象的。
这意味着生命周期本身不做任何实际的工作。在Maven的设计中,实际的任务(如编译源代码)都交由插件来完成。maven命令行的输入往往就对应了生命周期阶段,如mvn package就表示执行默认生命周期阶段package(构建)。

  • 生命周期和插件两者协同工作,密不可分。
  • 生命周期是一系列有序的生命周期阶段的集合,对所有的构建过程进行了抽象和统一。
  • Maven可以支持许多不同的生命周期,最常用的是Maven生命周期。

包括:

清理
初始化
编译
测试
打包(package)
集成测试
验证
部署
站点生成

以上的每个生命周期阶段都可以绑定一个或者多个插件行为,而且Maven为大多数构建步骤编写并绑定了默认插件。
比如package这个生命周期阶段的编译任务可能就会调用maven-jar-plugin来完成,测试任务就会调用maven-surefire-plugin来完成。

坐标

Maven坐标定义了一组标识,它们可以用来唯一标识一个项目,一个依赖,或者Maven POM里的一个插件。

Maven项目坐标的构成元素:groupId, artifactId, version和packaging。这些组合的标识符拼成了一个项目的坐标。

但是packaging不是一个项目唯一标识符的必须部分。

Maven坐标通常用冒号来作为分隔符来书写,格式:groupId:artifactId:packaging:version。
比如:mavenbook:my-app:jar:1.0-SNAPSHOT.
这也适用于项目依赖,比如项目包含了一个对junit:junit:jar:3.8.1的依赖。

标识解释

1 groupId:

团体,公司,小组,组织,项目,或者其它团体的逆向域名。比如Apache Software的项目经常以org.apache作为groupId。

2 artifactId

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

3 version:

一个项目的特定版本。发布的项目有一个固定的版本标识来指向该项目的某一个特定的版本。正在开发中的项目用一个特殊的标识“SNAPSHOT”标记。正式发布版是“release”或“stable”标记。

4 packaging:

项目的类型,默认是jar,描述了项目打包后的输出。类型为jar的项目产生一个JAR文件,类型为war的项目产生一个web应用。

仓库(Repositories)

当你第一次运行Maven的时候,你会注意到Maven从一个远程的Maven仓库下载了许多文件。如果这个简单的项目是你第一次运行Maven,那么当触发resources:resource目标的时候,它首先会做的事情是去下载最新版本的Resources插件。在Maven中,构件和插件是在它们被需要的时候从远程的仓库取来的。初始的Maven下载包的大小相当的小(1.8兆),其中一个原因是这个初始Maven不包括多余的插件。它只包含了几近赤裸的最少值,而在需要的时候再从远程仓库去取。Maven自带了一个用来下载Maven核心插件和依赖的远程仓库地址/ http://repo1.maven.org/maven2 。你常常会写这样一个项目,这个项目依赖于一些既不免费也不公开的包。在这种情况下,你需要要么在你组织的网络里安装一个定制的仓库,要么手动的安装这些依赖。默认的远程仓库可以被替换,或者增加一个你组织维护的自定义Maven仓库的引用。有许多现成的项目允许组织管理和维护公共Maven仓库的镜像。

是什么让Maven仓库成为一个Maven仓库的呢?

Maven仓库是通过结构来定义的,一个Maven仓库是项目构件的一个集合,这些构件存储在一个目录结构下面,它们的格式能很容易的被Maven所理解。在一个Maven仓库中,所有的东西存储在一个与Maven项目坐标十分匹配的目录结构中。你可以打开浏览器,然后浏览中央Maven仓库http://repo1.maven.org/maven2/ 来看这样的结构。你会看到坐标为org.apache.commons:commons-email:1.1的构件能在目录/org/apache/commons/commons-email/1.1/下找到,文件名为commons-email-1.1.jar。Maven仓库使用约定的标准目录格式来存储构件。

Maven从远程仓库下载构件和插件到你本机上,存储在你的本地Maven仓库里。一旦Maven已经从远程仓库下载了一个构件,它将永远不需要再下载一次,因为maven会首先在本地仓库查找插件,然后才是其它地方。在Windows XP上,你的本地仓库很可能在C:\Documents and Settings\USERNAME.m2\repository,在Windows Vista上,会是C:
\Users\USERNAME.m2\repository。在Unix系统上,你的本地仓库在~/.m2/repository。

如果你运行 mvn install 命令,Maven会把本地项目的构件安装到本地仓库。你能从这个命令的输出看到,Maven把本地项目的JAR文件安装到了本地Maven仓库。Maven在本地项目中通过本地仓库来共享依赖。如果你开发了两个项目—— 项目A和项目B——项目B依赖于项目A产生的构件。当构建项目B的时候,Maven会从本地仓库取得项目A的构件。

Maven仓库既是一个从远程仓库下载的构件的缓存,也允许你的项目相互依赖。

依赖管理 (Dependency Management)

创建一个项目所需要的资源引用称为依赖。

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

在Maven中的一个依赖不仅仅是一个JAR。它还包括了一个POM文件,这个POM可能也声明了对其它构件的依赖。这些依赖的依赖叫做传递性依赖,Maven仓库不仅仅存贮二进制文件,也存储了这些构建的元数据(metadata),才使传递性依赖成为可能。

让我们看一下这个目录:~/.m2/repository/junit/junit/3.8.1/。这里会有文件junit-3.8.1.jar 和junit-3.8.1.pom,还有Maven用来验证已下载构件准确性的校验和文件。需要注意的是Maven不只是下载JUnit的JAR文件,它同时为这个JUnit依赖下载了一个POM文件。Maven同时下载构件和POM文件的这种行为,对Maven支持传递性依赖来说非常重要。
当Maven通过一组Maven坐标来处理依赖构件的时候,它也会获取依赖构建的POM,通过依赖的POM来寻找传递性依赖。那些传递性依赖就会被添加到当前项目的依赖列表中。

Maven同时也提供了一种机制,能让你排除一些你不想要的传递性依赖。

Maven也提供了不同的依赖范围(dependency scope)。当一个依赖的范围是test的时候,说明它在Compiler插件运行compile 目标的时候是不可用的。它只有在运行compiler:testCompile和surefire:test目标的时候才会被加入到classpath中。当用Maven来创建WAR或者EAR,你可以配置Maven让它在生成的构件中捆绑依赖,你也可以配置Maven,使用provided范围,让它排除WAR文件中特定的依赖。provided范围告诉Maven一个依赖在编译的时候需要,但是它不应该被捆绑在构建的输出中。当你开发web应用的时候provided范围变得十分有用,你需要通过Servlet API来编译你的代码,但是你不希望Servlet API的JAR文件包含在你web应用的WEB-INF/lib 目录中。

站点生成和报告 (Site Generation and Reporting)

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

mvn site

这将会运行site生命周期阶段。它不像默认生命周期那样,管理代码生成,操作资源,编译,打包等等。Site生命周期只关心处理在src/site目录下的site内容,还有生成报告。在这个命令运行过之后,你将会在target/site 目录下看到一个项目web站点。载入target/site/index.html你会看到项目站点的基本外貌。它包含了一些报告,它们在左手边的导航目录的“项目报告”下面。它也包含了项目相关的信息,依赖和相关开发人员信息。

在这个站点上,你会注意到一些默认的报告已经可以访问了,有一个报告详细描述了测试的结果。这个单元测试报告描述了项目中所有单元测试的成功和失败信息。另外一个报告生成了项目API的JavaDoc。Maven提供了很完整的可配置的报告,像Clover报告检查单元测试覆盖率,JXR报告生成HTML源代码相互间引用,这在代码审查的时候非常有用,PMD报告针对各种编码问题来分析源代码,JDepend报告分析源代码中各个包之间的依赖。通过在pom.xml中配置那些报告被包含在构建中,站点报告就可以被定制了。

自己动手体会一下

通过一个经典的控制台 Hello world! 程序来体会maven的使用过程,包括创建、编译、测试、打包 ,并运行程序。

第一步:定位目录

在命令窗口中定位到将要创建项目的目录下。比如我的是:D:\Project\mavenTest\quickstart>

第二步:创建项目

使用archetype插件创建项目,输入以下命令:mvn archetype:generate ,回车,等。。。 然后,不出意外的话,你会看到屏幕输出了上千种archetype支持的项目类型。在末尾你会看到要求你输入的地方,就是这个:Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 756: 不翻译了,你一定要能看懂。

因为我们要创建的是一个简单的示例程序,所以什么都不输入,直接回车。
屏幕输出maven-archetype-quickstart项目类型的几个不同版本.
输入对应的序号(我输入的是6),然后回车。

按照屏幕输出,依次输入:groupId,artifactId,version,package. 

屏幕会输出你填写的项目信息,要求你确认,输入 Y ,回车,确认。

maven会根据你的设置开始下载依赖文件并创建项目。 当你看到Build Success时,项目就被创建好了,打开你的项目位置查看你的项目。maven在项目根目录下生成了一个POM.xml文件,这个是项目对象模型描述文件,maven就是根据这个文件的描述来构建你的项目的,打开看一下。

第三步:编译项目

使用compiler插件创建项目,输入以下命令:mvn compiler:compile ,回车,等。。。
maven开始下载依赖文件并编译项目。 当你看到Build Success时,项目就被编译好了,你还可以看到详细的编译结果信息。

第四步:打包项目 / 构建项目

使用maven默认的生命周期阶段命令package来打包项目,输入以下命令:mvn package ,回车,等。。。
maven开始下载依赖文件并编译项目。 当你看到Build Success时,项目就被打包好了,你还可以看到详细的编译结果信息。项目的根目录会出现一个target目录,存放了项目打包后的文件。

当然,你也可以不使用maven生命周期的默认package命令,而是自己动手使用多个插件来完成这个任务。

第五步:运行项目

如果前边的都成功完成的话,现在就可以运行一下项目看看结果了。

命令行输入:java -cp target/quickstart-1.1.jar maven.archetype.quickstart.App 回车。
应该输出了Hello world!


到这里为止,你已经了解了maven最核心的概念,明白了maven的结构,而且亲自使用maven成功构建了一个项目。

所以,本文到此就结束了。

接下来,到实际的工作中去使用maven,不断磨练自己的技艺吧!

附录

apache maven 官网

基于 Jenkins 快速搭建持续集成环境

maven的快速设置

maven核心插件列表

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • |-1-更新内容[6.从仓库解析依赖的机制(重要)] 1Maven仓库作用 仓库用来存储所有项目使用到构件,在ma...
    zlcook阅读 5,961评论 0 25
  • Maven的基本了解 什么是Maven? Maven就是Apache下的一个开源项目。它是用纯java开发的。是一...
    Bcome阅读 2,684评论 0 7
  • 我jdk版本是1.7.0_95,在网上查了一下1.7属于java7maven3.3+版本都支持java7,所以我使...
    liangxifeng833阅读 1,236评论 0 2
  • 首先私服是一种衍生出来的特殊的Maven远程仓库,构建私服的好处请看3.5私服 可以帮助大家建立私服的仓库管理软件...
    zlcook阅读 10,435评论 0 32
  • 一直以来,便很喜欢三毛的这句话:如果有来生,我愿做一棵树。站成永恒,没有悲欢的姿势。一半在尘土里安详,一半...
    2401期待阅读 282评论 0 1