《Maven权威指南》读书笔记

一、apache  maven  介绍

      1、maven是什么

绝大部分Maven用户都称Maven是一个"构建工具":一个用来把源代码构建成可发布的构件的工具。 构建工程师和项目经理会说Maven是一个更复杂的东西:一个项目管理工具。那么区别是什么? 像Ant这样的构建工具仅仅是关注预处理,编译,打包,测试和分发。像 Maven 这样的一个项目管理工具提供了构建工具所提供功能的超集。 除了提供构建的功能,Maven还可以生成报告,生成Web站点,并且帮助推动工作团 队成员间的交流。

一个更正式的 Apache Maven1 的定义: Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生 命周期(ProjectLifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。 当你 使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后 Maven 可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的 )插件。

2、约定优于配置 

 Maven通过给项目提供明智的默认行为来融合这个概念。 在没有自定义的情况下,源代码假定是在 /content-zh/src/main/java,资源文件假定是在/contentzh/src/main/resources。测试代码假定是在 /content-zh/src/test 。项目假定会产生一个 JAR 文件。Maven假定你想要把编译好的字节码放到/contentzh/target/classes 并且在 /content-zh/target 创建一个可分发的 JAR 文件。

Maven 对约定优于配置的应用不仅仅是简单的目录位置,Maven 的核心插件使用了一组通用的约定,以用来编译源代码,打包可分发的构件,生成 we b 站点,还有许多其他的过程。

3、基于maven插件的全局性重用

Maven 的核心其实不做什么实际的事情,除了解析一些 XML 文档,管理生命周期与插件之外,它什么也不懂。Maven 被设计成将主要的职责委派给一组Maven 插件,这些插件可以影响 Maven 生命周期,提供对目标的访问。绝大多数 Maven 的动作发生于Maven 插件的目标,如编译源码,打包二进制代码,发布站点和其它构建任务。 你从Apache 下载的 Maven 不知道如何打包 WAR 文件,也不知道如何运行单元测试,Maven大部分的智能是由插件实现的,而插件从 Maven 仓库获得。事实上,第一次 你用全新的 Maven 安装运行诸如 mvn install 命令的时候,它会从中央 Maven 仓库下载大部分核心 Maven 插件。这不仅仅是一个最小化 Maven 分发包大小的技巧,这种方 式更能让你升级插件以给你项目的构建提高能力。Maven 从远程仓库获取依赖和插件的这一事实允许了构建逻辑的全局性重用。

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

项目使用 Compiler 插件进行编译

4、apache   maven

• Maven 拥有约定,因为你遵循了约定,它已经知道你的源代码在哪里。它把字节码放到 target/classes ,然后在 target 生成一个 JAR 文件。
• Maven 是声明式的。你需要做的只是创建一个 pom.xml 文件然后将源代码放到默认的目录。Maven 会帮你处理其它的事情。
• Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。

Maven 以插件的形式为一些一般的项目任务提供了内置的智能。如果你想要编写运行单元测试,你需要做的只是编写测试然后放到 /content-zh/src/test/java ,添加一个对于 TestNG 或者 JUnit 的测试范围依赖,然后运行 mvn test 。如果你想要部署一个web 应用而非 JAR ,你需要做的是改变你的项目类型为 war ,然后把你文档根目录置为/content-zh/src/main/webapp 。


二、一个简单的maven项目

1、创建一个简单的项目

开始一个新的Maven项目,在命令行使用MavenArchetype插件。

$ mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 \
-DartifactId=simple \
-DpackageName=org.sonatype.mavenbook

archetype:create称为一个Maven目标 (goal)。如果你熟悉Apache Ant,一个Maven目标类似于一个Ant目标 (target);它们都描述了将会在构建
中完成的工作单元 (unit of work)。而像-Dname=value这样的对是将会被传到目标中的参数,它们使用-D属性这样的形式1,类似于你通过命令行向Java虚拟 机传递系统属性。archetype:create这个目标的目的通过archetype快速创建一个项目。在这里,一个archetype被定义为“一个原始的模型或者类型,在它之后 其它类似的东西与之匹配;一个原型(prototype)”。Maven有许多可用的archetype,从生成一个简单的Swing应用,到一个复杂的Web应用。本章我们用最基 本的archetype来创建一个入门项目的骨架。这个插件的前缀是“archetype”,目标为”create”。


¶ Maven Archtype插件创建了一个与artifactId匹配的目录——simple。这是项目的基础目录。
· 每个项目在文件pom.xml里有它的项目对象模型 (POM)。这个文件描述了这个项目,配置了插件,声明了依赖。

我们项目的源码了资源文件被放在了src/main目录下面。在我们简单Java项目这样的情况下,这个目录包含了一下java类和一些配置文件。在其它的项目中,它可能是web应用的文档根目录,或者还放一些应用服务器的配置文件。在一个Java项目中,Java类放在src/main/java下面,而classpath资源文件放在src/main/resources下面。

我们项目的测试用例放在src/test下。在这个目录下面,src/test/java存放像使用JUnit或者TestNG这样的Java测试类。目录src/test/resources下存放测试classpath资源文件。

2、构建项目 mvn install

想要构建打包这个应用,在包含pom.xml的目录下运行mvn install。

你已经创建了,编译了,测试了,打包了,并且安装了(installed)最简单的Maven项目

最开始的几个元素——groupId,artifactId, packaging, version——是Maven的坐标(coordinates),它们唯一标识了一个项目。name和url是POM提供的描述性元素,它们给人提供了可阅读的名字,将一个项目关联到了项目web站点。


3、maven插件和目标

一个Maven插件是一个单个或者多个目标的集合。Maven插件的例子有一些简单但核心的插件,像Jar插件,它包含了一组创建JAR文件的目标,Compiler插件,它包含了一组编译源代码和测试代码的目标,或者Surefire插件,它包含一组运行单元测试和生成测试报告的目标。

一个目标是一个明确的任务,它可以作为单独的目标运行,或者作为一个大的构建的一部分和其它目标一起运行。一个目标是Maven中的一个“工作单元(unit ofwork)”。目标的例子包括Compiler插件中的compile目标,它用来编译项目中的所有源文件,或者Surefire插件中的test目标,用来运行单元测试。目标通过配置属性进行配置,以用来定制行为。

Maven的核心对你项目构建中特定的任务几乎毫无所知。就它本身来说,Maven不知道如何编译你的代码,它甚至不知道如何制作一个JAR文件,它把所有这些任务代理给了Maven插件,像Compiler插件和Jar插件,它们在需要的时候被下载下来并且定时的从Maven中央仓库更新。当你下载Maven的时候,你得到的是一个包含了基本躯壳的Maven核心,它知道如何解析命令行,管理classpath,解析POM文件,在需要的时候下载Maven插件。通过保持Compiler插件和Maven核心分离,并且提供更新机制,用户很容易能使用编译器最新的版本。通过这种方式,Maven插件提供了通用构建逻辑的全局重用性,有不会在构建周期中定义编译任务,有使用了所有Maven用户共享的Compiler插件。如果有个对Compiler插件的改进,每个使用Maven的项目可以立刻从这种变化中得到好处。

4、maven生命周期   

命令行并没有指定一个插件目标,而是指定了一个Maven生命周期阶段。一个阶段是在被Maven称为“构建生命周期”中的一个步骤。生命周期是包含在一个项目构建中的一系列有序的阶段。Maven可以支持许多不同的生命周期,但是最常用的生命周期是默认的Maven生命周期,这个生命周期中一开始的一个阶段是验证项目的基本完整性,最后的一个阶段是把一个项目发布成产品。生命周期的阶段被特地留得含糊,单独的定义为验证(validation),测试(testing),或者发布(deployment),而他们对不同项目来说意味着不同的事情。

插件目标可以附着在生命周期阶段上。随着Maven沿着生命周期的阶段移动,它会执行附着在特定阶段上的目标。每个阶段可能绑定了零个或者多个目标。

在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 阶段。这个目标运行所有的测试并且创建那些捕捉详细测试结果的输出文件。默认情况下,如果有测试失败,这个目标会终止。

jar:jar
Jar插件的jar目标绑定到了package 阶段。这个目标把输出目录打包成JAR文件。



5、maven坐标

这就是项目对象模型(POM),一个项目的声明性描述。当Maven运行一个目标的时候,每个目标都会访问定义在项目POM里的信息。当jar:jar目标需要创建一个JAR文件的时候,它通过观察POM来找出这个Jar文件的名字。当compiler:compile任务编译Java源代码为字节码的时候,它通过观察POM来看是否有编译目标的参数。目标在POM的上下文中运行。目标是我们希望针对项目运行的动作,而项目是通过POM定义的。

groupId, artifactId, version和packaging。这些组合的就像任何其它的坐标系统,一个Maven坐标是一个地址,即“空间”里的某个点:从一般到特殊。当一个项目通过依赖,插件或者父项目引用和另外一个项目关联的时候,Maven通过坐标来精确定位一个项目。Maven坐标通常用冒号来作为分隔符来书写,像这样的格式:groupId:artifactId:packaging:version。

6、maven 仓库

当你第一次运行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仓库既是一个从远程仓库下载的构件的缓存,也允许你的项目相互依赖

7、maven  依赖管理

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

需要注意的是Maven不只是下载JUnit的JAR文件,它同时为这个JUnit依赖下载了一个POM文件。Maven同时下载构件和POM文件的这种行为,对Maven支持传递性依赖来说非常重要。
当你把项目的构件安装到本地仓库时,你会发现在和JAR文件同一目录下,Maven发布了一个稍微修改过的pom.xml的版本。存储POM文件在仓库里提供给其它项目了该项目的信息,其中最重要的就是它有哪些依赖。如果项目B依赖于项目A,那么它也依赖于项目A的依赖。当Maven通过一组Maven坐标来处理依赖构件的时候,它也会获取POM,通依赖的POM来寻找传递性依赖。那些传递性依赖就会被添加到当前项目的依赖列表中。

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

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

当为项目创建JAR文件的时候,它的依赖不会被捆绑在生成的构件中,他们只是用来编译。


8、多模块项目

一个多模块项目通过一个父POM引用一个或多个子模块来定义

注意simple-parent定义了一组Maven坐
标:groupId是org.sonatype.mavenbook,artifactId是simple-parent,version是1.0。
这个父项目不像之前的项目那样创建一个JAR或者一个WAR,它仅仅是一个引用其它
Maven项目的POM。像simple-parent这样仅仅提供项目对象模型的项目,正确的的打包
类型是pom。pom.xml中下一部分列出了项目的子模块。这些模块在modules元素中定义,
每个modules元素对应了一个simple-parent/目录下的子目录。Maven知道去这些子目录
寻找pom.xml文件,并且,在构建的simp-parent的时候,它会将这些子模块包含到要构
建的项目中。

当Maven执行一个带有子模块的项目的时候,Maven首先载入父POM,然后定位所有的子
模块POM。Maven然后将所有这些项目的POM放入到一个称为Maven 反应堆(Reactor)的
东西中,由它负责分析模块之间的依赖关系。这个反应堆处理组件的排序,以确保相互
独立的模块能以适当的顺序被编译和安装。
注意
除非需要做更改,反应堆一直维持定义在POM中的模块的顺序。为此一个有
帮助的思维模型是,那些依赖于兄弟项目的项目在列表中被“向下按”,直
到依赖顺序被满足。在很少的情况下,重新安排你构建的模块顺序可能很方
便——例如你想要一个频繁的不稳定的模块接近构建的开端。
一旦反应堆解决了项目构建的顺序,Maven就会在多模块构建中为每个模块执行特定的
目标。本例中,你能看到Maven在simple-webapp之前构建了simple-weather,为每个子
模块执行了mvn clean install。
注意
当你在命令行运行Maven的时候你经常会在任何其它生命周期阶段前指
定clean生命周期阶段。当你指定clean,你就确认了在编译和打包一个应用
之前,Maven会移除旧的输出。运行clean不是必要的,但这是一个确保你正
执行“干净构建”的十分有用的预防措施。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值