一、Maven简介
Maven是一个开源的构建工具,它可以帮助我们管理项目的构建过程,管理项目的生命周期,jar包依赖
关系等。Maven配合持续集成可以实现自动化的编译、测试、打包、发布等强大的功能,尤其在持续集成
上有为我们带来了很大便利。
二、Maven的简单命令及配置
1、下载Maven https://maven.apache.org
2、解压并配置环境变量
解压Maven到任意目录:
配置环境变量:
新建变量 M2_HOME,值为Maven主目录
在Path中添加 Maven的bin目录
3、测试Maven
4、更改Maven 默认仓库地址
默认情况下Mavne 会将jar包插件等下载到 ${user.home}/.m2/repository 下,在Windows 系统下通常是用户目录
下的.m2隐藏文件夹,这个文件夹在C盘,我们可以通过更改 Maven的配置文件 M2_HOME/conf/setting.xml 来
更改默认的本地仓库位置
6、Eclipse中设置maven
6.1、在Eclipse中设置使用自己下载的Maven
Windows–>Preferences–>Maven–>Installations–>add
然后勾选新添加的 Mavne 并应用设置
在选择 User Setting 设置 配置文件
第一个 Global Setting 为全局设置,一般选择 M2_HOME/conf/setting.xml;User Setting 是用户设置,一般copy 一份 setting.xml
到任意位置,然后根据自己需要改变一些内容;Maven的配置文件同样遵循”就近原则”;也就是说 User Setting 可以覆盖 Global
Setting;如果仅仅自己使用的话,也可以懒一点 两个都选择 M2_HOME/conf/setting.xml,然后只更改 一个配置文件就行了。
三、Maven的使用
1、在Eclipse中建立Mavne项目
首先 New 一个Maven Project
然后直接下一步(让你选择工作空间啥的,默认就行)
选择骨架类型,一般常用的 是 quickstart 和 web app;骨架的意思是项目的目录结构,maven采用约定优于配置
的理念,项目结构已经约定好了,有兴趣可以自己打开工作空间看一下
填写项目坐标(如果为一个模块,写坐标打包后可被其他项目引用);Artifact ID将作为项目名称。
2、简单的 jar 包管理
Maven可以很好的为我们管理jar 包中的依赖关系,而我们不必进行像以前一样去下载 jar包,然后添加class path
这种繁琐的操作,使用Maven后只要我们得知了该jar的仓库坐标,在POM文件中添加其坐标后,Maven将自动下载
并将其加入class path 中。假设现在我们需要使用SpringMVC,首先到 maven仓库 搜索其坐标
然后打开选择一个版本
复制Maven坐标
稍等片刻,Maven自动下载jar包并加入classpath中
3、maven的请求下载jar包工作流程如下图所示
4、Maven的常用命令
#编译命令
#执行此命令 maven将自动编译src/main/java 下的java文件到
#targetclasses目录
mvn compile
#测试命令
#执行此命令 maven将自动编译并执行src/test/java 下的java文件
#maven支持JUnit、TestNG等测试框架,@Test注解的方法将自动被执行
#具体可参考 http://seanzhou.iteye.com/blog/1393858
mvn test
#清理命令
#执行此命令将会清空 target目录,清空相关垃圾缓存文件
mvn clean
#打包命令
#执行此命令将对当前项目根据pom文件的描述进行打包
#可打包为 jar、war 等文件格式,便于其他项目使用
mvn package
#安装发布命令
#执行此命令 将自动将项目打包为jar包并根据pom文件内描述坐标
#发布到本地Respoitory中,其他项目可根据其坐标引用
mvn install
#创建骨架
#执行此命令可快速创建maven的项目骨架(文件目录结构和pom文件)
mvn archetype:generate
在Eclipse中可右键项目或POM文件,选择 Run AS 中的 Maven build…选项手动输入多个命令,
Maven将依次执行,截图如下
5、项目模块间的引用
在实际开发中,通常我们将项目分为N多模块进行开发,我们可以使用Maven建立多个项目,然后如果项目模块关联时,
比如A模块要调用B模块的方法,我们只需在B项目上运行 mvn clean 、mvn install 命令,将其发布到本地仓库,其他
模块可根据其坐标直接引入即可
6、Maven中的隐含变量
在项目多模块的配置时,groupid往往是重复的,某些高级设置时某些位置也可能是重复的,Maven为我们提供了通过变量
引用的方式来动态拿到指定值
Maven提供了三个隐式的变量可以用来访问 环境变量、POM信息和Maven Settings:
env变量
env变量,暴露了你操作系统或者shell的环境变量。如在Maven POM中一个对${env.PATH}的引用将会被${PATH}
环境变量替换,在Windows中为%PATH%.
project变量
project变量暴露了POM,是使用最多的一个变量,可以使用点标记(.)的路径来引用POM元素的值;如下图
具体值参考如下(eclipse一般都有提示,没有自行引入maven的dtd文件,此段内容引自 iteye):
#项目根目录
${basedir}
#构建目录,缺省为target
${project.build.directory}
#构建过程输出目录,缺省为target/classes
${project.build.outputDirectory}
#产出物名称,缺省为 ${project.artifactId}-${project.version}
${project.build.finalName}
#打包类型,缺省为jar
${project.packaging}
#当前pom文件的任意节点的内容
${project.xxx}
7、Maven的依赖
每个项目都有其classpath,在Maven管理下的项目实际上有3个classpath(编译classpath、测试classpath、运行classpath);
每个被maven管理的jar包在这三种classpath是否生效及如何选择称之为maven的依赖管理,Maven依赖管理可通过
<dependency> 下的 <scope>标签设置,其值含义如下
compile: 编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。
test: 测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候才需要。
provided: 已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
runtime: 运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
system: 系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。systemPath元素可以引用环境变量,如:<systemPath>${java.home}/lib/rt.jar</systemPath>
import(Maven 2.0.9及以上): 导入依赖范围。该依赖范围不会对三种classpath产生实际的影响
例如我们设置JUint,只有测试时用到,scope 只需设置成 test即可
Maven依赖传递性:
当A项目依赖某一jar包,比如log4j 时,将其发布到本地仓库后,B项目进行引用时,则同样会依赖log4j;这种
情况称之为 Maven的依赖传递,当scope设置为test时,则依赖不会被传递。
Maven复杂依赖:
7.1、单项目依赖多模块,多模块中jar包版本冲突,如下图
在此种情况下,Maven无法自动判断jar包x的版本;模块C中的jar包x版本取决于C模块的pom文件中 模块A、B
的书写位置,也就是说谁先写在上面,那么就先使用谁的,如下
7.2、单项目依赖多模块,多模块中jar包版本冲突,但单项目(模块C)中jar包x版本却并非取决于书写顺序,情况如下图
假设模块C的pom文件中仍是先写得模块A;但此时在 模块C中 jar包x的版本仍是2.0;原因是模块A依赖了jar包K,而jar包K
又依赖了jar包x;相当于jar包x到模块C之间存在二级关系,此时Maven的依赖选择以最近的为主,如果距离(层级)相同,
那么再根据书写顺序判定选择那个,否则优先选择距离(层级)最近的,在Eclipse中可通过视图查看依赖层级关系,如下
Maven依赖的排除:
当项目模块中存在jar包冲突时,或想使用某个模块中指定的jar包版本,我们可以使用<exclusions>标签进行排除某个jar包,如下
四、Maven的聚合与继承
1、Maven的聚合
我们已经知道Maven中多模块(项目)是可以互相引用的,但在实际开发中往往会遇到一些问题;当模块足够多时,
每一次编译打包也就意味着我们要在N多个模块(项目)上执行 clean 、package 等命令,这显然是不能接受的;
Maven为我们提供了项目(模块)的聚合功能,也就是说模块最终要统一到一个项目,每次打包编译,我们只需对
“总项目” 进行即可,而无需关心各个模块。
1.1、首先我们创建一个没有骨架的项目(new 一个Maven项目),在下面这步注意要勾选”跳过骨架选择”
1.2、填入相关信息,注意打包形式选择pom
1.3、创建好项目以后我们编辑pom文件,使用<modules>标签指定该项目聚合哪些项目(模块)
<module>标签使用相对路径,指向其他项目(模块),一般都是 ../xxxx
1.4、此时对聚合项目执行一下 clean compile 测试一下,控制台打印如下,可以看出,Maven依次对3个项目执行了相关操作
2、Maven的集成
当成功聚合了多个模块以后,我们还会发现在每个项目模块中存在大量的相同代码,这让我们感觉很不爽;
有点”造轮子”的嫌疑,当然Maven同样支持继承的操作,也就是说将模块中的相同代码放到父类项目(模块)中,
其他模块只需继承即可使用,同时也能很好地解决jar包版本冲突问题
2.1、首先看一下 各个模块的pom文件,这里面很多都是重复的
2.2、我们同样新建一个Maven项目,跳过骨架创建
2.3、然后我们提取其他子模块pom文件中的共有部分放入父pom文件中(以下为父pom文件),包括共有的定义以及
每个项目的依赖jar包(依赖的jar包需要使用<dependencyManagement> 标签来管理)
2.4、此时我们可以在子项目模块中通过<parent>标签指定继承的Pom文件
注意:聚合<module>标签指定的是相对的项目,而继承指定的则是相对的pom文件
2.5、当继承后我们便可以删除公有的相同内容,如 <url>等;同时依赖的jar包也可不必指定版本
2.6、到此,继承完成,由于依赖jar包都来自父pom,同时子pom依赖的jar包无需书写版本,这样在一定程度上保证了jar包版本
的统一性;同时我们可以发现,聚合和继承十分相似,其实我们可以将聚合也加入到这个pom中来,实现一个项目对多个项目
(模块)的继承与聚合,如下为示例的pom文件
<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>me.mritd.Test1</groupId>
<artifactId>MavenParent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../MavenTest1</module>
<module>../MavenTest2</module>
<module>../MavenTest3</module>
</modules>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
你这maven教程写的好详细哦,请接受我的膜拜