Maven基础知识学习笔记
1、什么是Maven
Apache Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一个标准几何,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
2、什么是pom?
pom作为项目对象模型。
基本内容:
POM包括了所有的项目信息。
POM定义了最小的maven2元素,允许groupId,artifactId,version等所有需要的元素;groupId,,artifactId, version:描述了依赖的项目唯一标志
- groupId:项目或者组织的唯一标志,并且配置时生成的路径也是由此生成,如com.taobao.cmp生成的相对路径为:/com/taobao/cmp
- artifactId:groupId下的表示一个单独项目的唯一标识符,默认为jar
- version:项目的版本
- packaging:打包的机制,如pom, jar, maven-plugin, ejb, war, ear, rar, par
<groupId>com.taobao.XXXtest</groupId>
<artifactId>XXX-qatest</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
3、POM中的关系:
主要为依赖,合成,继承
3.1依赖关系(dependencies相关):
Maven提供传递依赖:
A->B B->C C->D 则 A依赖D;
A->B->D1.0 A->D2.0 则 A依赖D2.0
A->E1.0 A->E2.0 则 A依赖E1.0
这种依赖方式遵循的原则:最近原则、最先原则(since maven 2.0.9)。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
3.1.1依赖的范围(scope)
compile(缺省值 ),test,runtime,provided;
依赖范围(scope)主源码classpath可用测试源码classpath可用会被打包compile 缺省值TRUETRUETRUEtestFALSETRUEFALSEruntimeFALSETRUETRUEprovidedTRUETRUEFALSE
Junit包一般来说只有在运行测试的时候需要它,对上一个例子进行改进:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
再举个例子,在开发javaee应用的时候一定会用到servlet-api,它对于主源码和测试源码都是必要的,因为我们的代码中会引入servlet-api的包。但是,在打包的时候,将其放入WAR包就会有问题,因为web容器会提供servlet-api,如果我们再将其打包就会造成依赖冲突,解决方案如下:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
3.1.2依赖归类
随着项目的增大,依赖越来越多。例如依赖了很多spring的jar:org.springframework:spring;org.springframework:spring-mock;org.springframework: spring-aspects,它们的groupId是相同的,artifactId不同,为了管理其版本,可以采用下面这种方式
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<properties>
<spring.version>2.0.7</spring.version>
</properties>
这里定义了一个Maven属性,其名称为spring.version,值是2.0.7。在这个POM中,能用${spring.version}的方式来引用该属性。所有spring相关的依赖的version元素现在都成了${spring.version},当Maven运行的时候,它会自动用值2.0.7来替换这个引用。
当需要升级spring的时候,只要更改一个地方便可,而且现在能很高的保证所有的spring依赖包都是同一个版本
3.1.3分类器(classifier)
GAV是Maven坐标最基本最重要的组成部分,但GAV不是全部。还有一个元素叫做分类器(classifier),90%的情况你不会用到它,但有些时候,分类器非常不可或缺。
例如:当测试工程需要依赖一个war包时,pom文件不支持直接依赖war包,所以需要在测试工程里依赖war的地方加上<classifier>classes</classifier>,表示依赖编译好的文件。
<dependencies>
<dependency>
<groupId>com.taobao.XXX</groupId>
<artifactId>XXX-web</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>classes</classifier>
</dependency>
</dependencies>
注意到maven下载了一个名为XXX-web-1.0.0-SNAPSHOT-classes.jar的文件。其命名模式实际上是<artifactId>-<version>-<classifier>.<packaging>。
3.1.4依赖管理(dependencyManagement)
当只有一个Maven模块的时候,完全不需要看这个部分。
除测试工程和一些简单的工程中,一般都有很多Maven模块,而且往往这些模块有很多依赖是完全相同的,A模块有个对spring的依赖,B模块也有,它们的依赖配置一模一样,同样的groupId, artifactId, version,或者还有exclusions, classifer。这是一种重复,重复就意味着潜在的问题,Maven提供的dependencyManagement就是用来消除这种重复的。
正确的做法是:
1. 在父模块中使用dependencyManagement配置依赖
2. 在子模块中使用dependencies添加依赖
dependencyManagement实际上不会真正引入任何依赖,dependencies才会。但是,当父模块中配置了某个依赖之后,子模块只需使用简单groupId和artifactId就能自动继承相应的父模块依赖配置。
父模块配置:
<dependencyManagement>
<dependencies>
<!–=====***=====–>
<dependency>
<groupId>com.taobao.common.***</groupId>
<artifactId>common-***</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
子模块配置:
<dependencies>
<dependency>
<groupId>com.taobao.common.***</groupId>
<artifactId>common-***</artifactId><!—父模块中已经设置了版本,这里不需要设置version–>
</dependency>
</dependencies>
3.1.5独占性
由于Maven提供传递依赖,这样造成一个项目中,引用了同一jar包的不同版本,造成jar包冲突。解决办法:使用exclusion:
<dependency>
<groupId>com.taobao.XXX</groupId>
<artifactId>XXX-biz</artifactId>
<version>1.0.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>dbunit</groupId>
<artifactId>dbunit</artifactId>
</exclusion>
</exclusions>
</dependency>
引用XXX-biz jar包,不引用 dbunit jar包
3.2合成(或者多个模块)关系:
一个项目有多个模块,也叫做多重模块,或者合成项目。
<modules>
<module>XXX-biz</module>
<module>XXX-web</module>
</modules>
3.3继承关系:
Maven 提供了强大的项目继承。以下面的配置为例,此时XXX-biz中使用和父模块相同的groupId
<parent>
<groupId>com.taobao.XXX</groupId>
<artifactId>XXX</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>XXX-biz</artifactId>
<version>1.0.0-SNAPSHOT</version>