maven分享
唐韧 ren.tangr@alibaba-inc.com
第一部分,maven介绍及必须了解得概念
What is maven?
开发人员理解maven,是一个构建工具,“一个用来把源代码构建成可发布的构件的工具。” -- 像Ant这样的构建工具仅仅是关注预处理,编译,打包,测试和分发。
项目经理理解maven,是一个项目管理工具 “提供了构建工具所提供功能的超集。 除了提供构建的功能,Maven 还可以生成报告,生成Web 站点,并且帮助推动工作团 队成员间的交流。”
正式的定义:Maven 是一个项目管理工具,它包含了一个
项目对象模型 (POM),
一组标准集合,
一个项目生命周期(ProjectLifecycle),
一个依赖管理系统(Dependency ManagementSystem),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。 当你使用Maven 的时候,你用一个明确定义的项目对象模型来描述你的项目,然后
Maven 可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
maven的内部规范是基于约定优于配置的
约定优于配置是一个简单的概念。 系统,类库,框架应该假定合理的默认值,而非要求提供不必要的配置。 好处是简化配置,提高框架使用效率;
maven也是如此,Maven 通过给项目提供明智的默认行为来融合这个概念。 在没有自定义的情况下,源代码假定是在
${basedir}/src/main/java,资源文件假定是在
${basedir}/src/main/resources。。测试代码假定是在 ${basedir}/src/test 。项目假定会产生一个 JAR 文件。Maven 假定你想要把编译好的字节码放到${basedir}/target/classes 并且在 ${basedir}/target 创建一个可发布的 JAR文件。
maven得插件机制也很多用到了约定优于配置的概念。就机制方面来说,Maven 的力量来自它的"武断",它有一个
定义好的生命周期和一组
知道如何构建和装配软件的通用插件。
但这套机制并不是强制式的,他是内部具备钩子,在必要是可以更改的。
maven核心是什么?
maven就是一个微内核。核心提供了对
配置文件的解析,
管理生命周期,
管理插件,
在合适的周期调用不同的插件。
maven的各种各样的业务逻辑都是通过各种各样职责各异的插件来提供的。
怎么和maven对话,让他为我们干活?
maven是个计算机软件工具,听不懂人话,和他讲话必须要用它的语言。 maven的语言就是pom(项目对象模型)和maven的指令。
pom项目对象模型:
它是包含了一组关于软件项目和软件开发的语义规则的载体。这个基于每一个项目定义的模型实现了如下特征:
依赖管理
由于项目是根据一个包含组标识符,构件标识符和版本的唯一的坐标定义的(
groupId,artifactId,version,这三个维度唯一确定一个构建标识)。项目间可以使用这些坐标来声明依赖。
远程仓库
和项目依赖相关的,我们可以使用定义在项目对象模型(POM)中的坐标来创建 Maven 构件的仓库。
和项目依赖相关的,我们可以使用定义在项目对象模型(POM)中的坐标来创建 Maven 构件的仓库。
全局性构建逻辑重用
插件被编写成和项目模型对象(POM)一起工作,它们没有被设计成操作某一个已知位置的特定文件。一切都被抽象到模型中,插件配置和自定义行为都在模型中进行。
插件被编写成和项目模型对象(POM)一起工作,它们没有被设计成操作某一个已知位置的特定文件。一切都被抽象到模型中,插件配置和自定义行为都在模型中进行。
工具可移植性/集成
像 Eclipse,NetBeans,和 InteliJ 这样的工具现在有共同的地方来找到项目的信息。在 Maven 出现之前,每个 IDE 都有不同的方法来存储实际上是自定义项目对象模型(POM)的信息。 Maven 标准化了这种描述,而虽然每个 IDE仍然继续维护它的自定义项目文件,但这些文件现在可以很容易的由模型生成(maven ide插件根据pom来生成)。
像 Eclipse,NetBeans,和 InteliJ 这样的工具现在有共同的地方来找到项目的信息。在 Maven 出现之前,每个 IDE 都有不同的方法来存储实际上是自定义项目对象模型(POM)的信息。 Maven 标准化了这种描述,而虽然每个 IDE仍然继续维护它的自定义项目文件,但这些文件现在可以很容易的由模型生成(maven ide插件根据pom来生成)。
pom 结构图:
总而言之,maven的pom.xml 为软件项目的语义一致性描述的开端提供了一个基础。
一个简单的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=" http://maven.apache.org/POM/4.0.0 " xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance " xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.udb</groupId>
<artifactId>udb.parent</artifactId><version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>udb.parent</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
maven重要目录及的配置文件介绍:
~/.m2/settings.xml
此文件是maven的总配置文件,默认配置位置是在${maven_home}/conf的,如果${user_home}/.m2/也存在,那么后者优先。
该文件包含了用户相关的认证,仓库和其它信息的配置,用来自定义Maven 的行为。
~/.m2/repository
该目录是你本地的仓库。当你从远程Maven 仓库下载依赖的时候,Maven 在你本地仓库存储了这个依赖的一个副本。 maven的依赖检查是先根据pom中项目的依赖查询本地库中是否存在依赖实体,如果不存在那么会在中心依赖仓库中下载到本地依赖仓库进行依赖引用。
什么是maven仓库、依赖管理是个什么意思?
maven把项目、子项目、依赖、插件都统一定义为称为构建(artifact)的最小单元。认为所有artifact都能够根据不同的场景及实际应用进行组合。
而对构建进行保存、管理的途径就是建立了一个称为maven构建仓库的概念。具体看图。
maven依赖管理及仓库管理架构图:
代码示例:
给一个maven项目添加依赖的片段
...
<dependencyManagement>
<dependencies>
<dependencies>
...
<dependency>
<artifactId>构件Id</artifactId>
<groupId>构件组Id</groupId>
<scope>依赖生效作用域</scope>
</dependency>
<dependency>
<artifactId>构件Id</artifactId>
<groupId>构件组Id</groupId>
<scope>依赖生效作用域</scope>
</dependency>
...
</dependencies>
</dependencyManagement>
</dependencies>
</dependencyManagement>
...
什么是maven生命周期?
默认maven生命周期表(phase)
validate | validate the project is correct and all necessary information is available. |
initialize | initialize build state, e.g. set properties or create directories. |
generate-sources | generate any source code for inclusion in compilation. |
process-sources | process the source code, for example to filter any values. |
generate-resources | generate resources for inclusion in the package. |
process-resources | copy and process the resources into the destination directory, ready for packaging. |
compile | compile the source code of the project. |
process-classes | post-process the generated files from compilation, for example to do bytecode enhancement on Java classes. |
generate-test-sources | generate any test source code for inclusion in compilation. |
process-test-sources | process the test source code, for example to filter any values. |
generate-test-resources | create resources for testing. |
process-test-resources | copy and process the resources into the test destination directory. |
test-compile | compile the test source code into the test destination directory |
process-test-classes | post-process the generated files from test compilation, for example to do bytecode enhancement on Java classes. For Maven 2.0.5 and above. |
test | run tests using a suitable unit testing framework. These tests should not require the code be packaged or deployed. |
prepare-package | perform any operations necessary to prepare a package before the actual packaging. This often results in an unpacked, processed version of the package. (Maven 2.1 and above) |
package | take the compiled code and package it in its distributable format, such as a JAR. |
pre-integration-test | perform actions required before integration tests are executed. This may involve things such as setting up the required environment. |
integration-test | process and deploy the package if necessary into an environment where integration tests can be run. |
post-integration-test | perform actions required after integration tests have been executed. This may including cleaning up the environment. |
verify | run any checks to verify the package is valid and meets quality criteria. |
install | install the package into the local repository, for use as a dependency in other projects locally. |
deploy | done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects. |
在上表中,maven的执行生命周期是自上而下的。
官方maven生命周期参考资料:
什么是maven插件?
简单来说,maven插件就是实现了maven定义的标准插件接口(org.apache.maven.plugin.Mojo)的Java类,maven通过对插件接口实类现进行回调的形式执行具体插件类中的插件逻辑,从而达到各种各样的目的。如生成eclipse项目描述文件,打包项目,发布项目,执行单元测试,生成项目报表数据等等各种功能。
maven插件架构静态模型图
org.apache.maven.plugin.Mojo : maven的插件接口,定义了maven插件的标准行为规范。
org.apache.maven.plugin.ContextEnabled : 这是一个标识接口,实现了该接口的具体插件会被maven内核注入相关上下文信息。
org.apache.maven.plugin.AbstractMojo : maven的抽象插件实现, 封装了一系列插件常规行为逻辑, 一般开发插件直接继承这个抽象类就o了。
(以clean-maven-plugin插件举例简单介绍下)
官方插件参考资料:
http://maven.apache.org/plugins/index.html
第二部分,Maven生命周期与插件的绑定
示意图:
maven的默认生命周期是maven项目的核心生命周期,那么生命周期中的每个phase对应的插件就是核心插件。
绑定过程代码示例:
<build>
<plugins>
<plugin>
<artifactId>compile</artifactId>
<groupId>org.maven.plugin.mojo</groupId>
<version>1.0</version>
<executions>
<execution>
<phase> compile</phase>
<goals>
<goal> complie</goal>
<goal> testCompile</goal>
</goals>
<configuration>
<some.config1>some.config1</some.config1>
<some.config2>some.config2</some.config2>
<some.config3>some.config3</some.config3>
</configuration>
</execution>
</executions>
<configuration>
<this.plugin.base.config1>base.config1</this.plugin.base.config1>
<this.plugin.base.config2>base.config2</this.plugin.base.config2>
</configuration>
</plugin>
<plugins>
<plugin>
<artifactId>compile</artifactId>
<groupId>org.maven.plugin.mojo</groupId>
<version>1.0</version>
<executions>
<execution>
<phase> compile</phase>
<goals>
<goal> complie</goal>
<goal> testCompile</goal>
</goals>
<configuration>
<some.config1>some.config1</some.config1>
<some.config2>some.config2</some.config2>
<some.config3>some.config3</some.config3>
</configuration>
</execution>
</executions>
<configuration>
<this.plugin.base.config1>base.config1</this.plugin.base.config1>
<this.plugin.base.config2>base.config2</this.plugin.base.config2>
</configuration>
</plugin>
</plugins>
</build>
第三部分,maven pom 规范介绍
总控文件规范:
总控文件( settings.xml)统一使用b2b定义好的settings.xml文件,放到~/.m2/下面
下载地址:~~~~
POM.xml是具备继承关系的, 下层子pom继承上层的内容,并可以覆盖上层内容。
所以我们pom层次设计总原则是:
把稳定的、可共用的pom信息移到上层,把相对不稳定的、特性的pom信息保留到下层
pom.xml 层次关系
第四部分,实战maven with our project
1,创建maven项目
创建一个maven项目有两种方式,一种是人肉通过maven的约束,创建相关目录以及pom.xml文件;第二种方式是通过maven提供的archetype插件进行项目创建;
archetype插件提供了模板化或者根据自定义化项目创建。
接下来我们使用archetype插件来创建项目。
$ mvn
archetype:create
-DgroupId=xxx -DartifactId=xxx
命令分析:
archetype :create紫色部分表示的是插件名, 红色部分是此插件的功能名, 表示使用archetype插件中的create功能。
-DgroupId=xxx -DartifactId=xxx这表示指定插件运行参数。当然此参数也不一定用在此插件中,也可能用在整个项目生命周期插件链的其他插件中。groupId表示项目group的idartifactId表示项目的标识idarchetype插件默认根据groupId设置包名,根据artifactId设置项目名
3,通过archetype创建好项目后,我们需要生成IDE的表述文件,方便IDE识别项目
$
mvn eclipse:eclipse -DdownloadJavadocs=true -DdownloadSources=true
使用eclipse插件生成eclipse的项目表述文件(.project)及类路径文件(.classpath)
这样,我们就可以通过eclipse 导入项目了。
2,定义pom.xml
略
3,构建maven项目
略
。。。。。。
具体见