Maven简介
Maven是做什么用的
Maven 是一个项目管理和构建的自动化工具。
Maven 使用惯例优于配置的原则。即它在要求没有定制之前,所有的项目都有如下的结构:
目录 | 目的 |
---|---|
${basedir} | 存放pom.xml 和所有的子目录 |
${basedir}/src/main/java | 项目的java 源代码 |
${basedir}/src/main/resources | 项目的资源,比如property 文件 |
${basedir}/src/test/java | 项目的测试类,比如JUnit 代码 |
${basedir}/src/test/resources | 测试使用的资源 |
${basedir}/target | 编译产生的文件 |
一个maven项目在默认情况下会产生JAR 文件,另外,编译后的classes 会放在 basedir/target/classes下面,JAR文件会放在 b a s e d i r / t a r g e t / c l a s s e s 下 面 , J A R 文 件 会 放 在 {basedir}/target 下面。
POM(Project Object Model)
Maven采用一种被称为project object model(POM) 的概念来管理项目,所有的项目配置信息都被定义在一个叫pom.xml 的文件中,包括定义项目的类型、名字、管理依赖关系、定制插件的行为等等。通过该文件,maven 可以管理项目的整个生命周期,包括编译、构建、测试、发布、报告等等。pom.xml 示例:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.maven.demo</groupId>
<artifactId>mavenDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mavenDemo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
在POM中,groupId,artifactId,packaging,version 叫作maven 坐标,它能唯一的确定一个项目。有了maven 坐标,我们就可以用它来指定我们的项目所依赖的其他项目、插件、或者父项目。一般maven 坐标写成如下格式:
groupId:artifactId:packaging:version
eg:
com.maven.demo:mavenDemo:jar:0.0.1-SNAPSHOT
示例demo 很简单,但是大项目一般会分成几个子项目,在这种情况下,每个子项目就会有自己的POM 文件,然后它们会有一个共同的父项目。这样只要构建父项目就能构建所有的子项目。子项目的POM 会继承父项目的POM。
另外,所有的POM都继承了一个Super-POM。Super-POM 设置了一些默认值,比如默认的目录结构,默认的插件等等,遵循惯例优于配置的原则。
POM解析
<project>: 所有pom.xml 文件中的顶层元素,申明了一些POM相关的命名空间以及xsd元素,用来约束maven的写法。
<modelVersion>:指POM使用的对象模型的版本。这个值很少改动,对于Maven2及Maven3来说,只能是4.0.0。
<groupId>:该值来源于我们创建项目时输入的“Group ID”。指明创建项目的组织或者小组的唯一标识。groupId是项目的关键标识,此标识以组织的完全限定名来定义。eg:org.apache.maven.plugins是所有Maven插件项目指定的groupId
<artifactId>:该值来源于我们创建项目时输入的“Artifact ID”。指明此项目产生的主要产品的基本名称。项目的主要产品通常是一个JAR 文件。第二,源代码包通常使用artifactId作为最后名称的一部分。典型的产品名称使用这个格式:\-\.\ (eg:myapp.jar)。
<version>:该值来源于我们创建项目时选择的“Version”。标识项目产品的版本号。Maven帮助你管理版本,可以经常看到SNAPSHOT这个版本,意思是快照,表明项目处于开发阶段,是不稳定版本。
<packaging>:指项目产生的主要产品格式。(eg:jar)
<name>:项目的显示名称。通常用于maven 产生的文档中。值默认为artifactId。
<url>:指定项目站点,通常用于maven 产生的文档中。
<properties>:项目的“Properties”。对应于在项目上右键->“Properties”。里面可以配合项目采用的编码方式等等。
<dependencies>:指项目的依赖。通常由很多的\组成,这里默认只有“junit-3.8.1”。
<dependency>:一个依赖单元。意思是本项目需要依赖一个”groupId 和artifactId 为junit,并且version 为3.8.1“的另外一个项目(默认packaging 为jar),其实就是”junit-3.8.1.jar”包。实际使用中,如果我们需要某个jar 包,就会添加一个单元,然后更新项目之后maven就会自动帮助我们下载我们需要的jar 包。
Maven插件
maven(mvn) 本身不会做太多事情,它不知道怎么样编译或者怎么样打包。它把构建的任务交给插件去做。插件定义了常用的构建逻辑,能够被重复利用。
优点:一旦插件有了更新,所有的maven 用户都能得到更新。
插件目标通常会写成:
pluginId:goalId
一个目标是一个工作单元,而插件则是一个或者多个目标的集合。比如Jar 插件,Compiler 插件,Surefire 插件等。Jar 插件包含建立Jar文件的目标,Compiler 插件包含编译源代码和单元测试代码的目标,Surefire 插件则是运行单元测试的目标
eg:用~$mvn archetype:generate 命令来生成一个项目
~$mvn archetype:generate -DgroupId=com.mycompany.helloworld -DartifactId=helloworld -Dpackage=com.mycompany.helloworld -Dversion=1.0-SNAPSHOT
其中:archetype是一个插件(pulgin)的名字,generate是目标(goal)的名字
用来:告诉maven执行archetype插件的generate目标来生成一个项目
另外:-Dname=value的格式用来指定选项属性
Maven生命周期(lifecycle phase)
生命周期指项目的构建过程,它包含了一系列的有序的阶段(phase),而一个阶段就是构建过程中的一个步骤。
生命周期阶段与插件目标的关系:一个生命周期阶段可以绑定多个插件目标。当maven 在构建过程中逐步的通过每个阶段时,会执行该阶段所有的插件目标
maven 能支持不同的生命周期,但是最常用的是默认的Maven生命周期(default Maven lifecycle)
示例~$mvn package用来构建项目
如果没有对maven 生命周期进行任何的插件配置或者定制的话,mvn package 会依次执行默认生命周期中直到包括package 阶段前的所有阶段的插件目标》》
process-resources阶段:resources:resources
compile阶段:compiler:compile
process-classes阶段:(阶段无目标)
process-test-resources阶段:resources:testResources
test-compile阶段:compiler:testCompile
test阶段:Surefire:test
prepare-package阶段:(阶段无目标)
package阶段:jar:jar
Maven依赖管理
在POM中,依赖关系是在dependencies部分中定义的
eg:用dependencies定义对Junit的依赖:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
maven提供了传递依赖的特性,传递依赖是指maven 会检测被依赖的jar文件,把它的依赖关系纳入最终解决的依赖关系链中(maven 不但下载了Junit-3.8.1.jar文件,还下载了它的POM 文件,maven就能检测Junit 的依赖关系,把它所需要的依赖也包括进来)
scope决定依赖关系的适用范围,在 POM 的 dependencies 部分中,scope 决定了依赖关系的适用范围。我们的例子中 junit 的 scope 是 test,那么它只会在执行 compiler:testCompile and surefire:test 目标的时候才会被加到 classpath 中,在执行 compiler:compile 目标时是拿不到 junit 的。
我们还可以指定 scope 为 provided,意思是 JDK 或者容器会提供所需的jar文件。比如说在做web应用开发的时候,我们在编译的时候需要 servlet API jar 文件,但是在打包的时候不需要把这个 jar 文件打在 WAR 中,因为servlet容器或者应用服务器会提供的。
scope 的默认值是 compile,即任何时候都会被包含在 classpath 中,在打包的时候也会被包括进去
Maven 库
当第一次运行 maven 命令的时候,你需要 Internet 连接,因为它要从网上下载一些文件。那么它从哪里下载呢?它是从 maven 默认的远程库(http://repo1.maven.org/maven2) 下载的。这个远程库有 maven 的核心插件和可供下载的 jar 文件。
但是不是所有的 jar 文件都是可以从默认的远程库下载的,比如说我们自己开发的项目。这个时候,有两个选择:要么在公司内部设置定制库,要么手动下载和安装所需的jar文件到本地库。
本地库是指 maven 下载了插件或者 jar 文件后存放在本地机器上的拷贝。在 Linux 上,它的位置在 ~/.m2/repository,在 Windows XP 上,在 C:\Documents and Settings\username.m2\repository ,在 Windows 7 上,在 C:\Users\username.m2\repository。当 maven 查找需要的 jar 文件时,它会先在本地库中寻找,只有在找不到的情况下,才会去远程库中找。
示例:~$mvn install 用来把项目安装到本地库
一旦一个项目被安装到了本地库后,你别的项目就可以通过 maven 坐标和这个项目建立依赖关系。