Maven是目前比较主流的项目管理工具之一,当然Gradle也是其中之一。它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
- pom:项目对象模型 (Project Object Model),项目的属性、依赖、构建、配置信息等都被抽象到项目对象模型里,定义了项目的基本信息;
Maven的特点:
- 微内核:大部分功能通过插件实现,主要用于XML文件的解析、管理生命周期;
- 约定优于配置。
Maven构建的步骤:
- 清理:清理以前旧的class文件
- 编译
- 测试
- 报告
- 打包
- 安装
- 部署
IDEA导入Maven项目,直接File–>open…–>选择pom.xml文件即可导入Maven工程,具体的依赖可以通过IDEA边界菜单栏Maven Project中的Dependencies。
1.1 坐标和依赖
maven中任何一个依赖、插件、项目的输出都可以叫做构件,任何一个构件都可以用一个规则来唯一标记,这个规则就是坐标,主要由以下元素构成(前三者通常是一个依赖的必要元素):
- groupId:必要属性,如果插件是maven官方提供了,那么此时可以省,定义当前Maven项目隶属的实际项目,通常取用反向域名;
- artifactId:必要属性,定义实际项目中中具体模板,通常就取实际的模块名字;
- version:必要属性,定义Maven项目当前所处的版本,如果继承自父类,那么这个属性可省自动使用父类版本;
- packaging:非必要,Maven的打包方式默认是jar,可以自己手动改;
- classifier:非必要,定义构件输出的一些附属构件,不常用,不能直接定义,由插件帮助生成;
- type:依赖的类型
- scope:依赖的范围
- optional:标识依赖是否可选
- exclusions:用来排除传递性依赖
<scope>
:依赖范围,maven的classpath总共有3套,编译一套、编译和执行测试一套、实际运行一套,默认参数是compile,三套classpath都有效;test,测试范围;provided:编译和测试有效;runtime:测试和运行范围;system:系统范围,慎用;他们三个作用的范围如下表所示:
scope | 编译 | 测试 | 运行 | 例子 |
---|---|---|---|---|
compile | Y | Y | Y | Spring-core |
test | - | Y | - | Junit |
provided | Y | Y | - | Servlet-Api |
runtime | - | Y | Y | JDBC驱动 |
system | Y | Y | - | 本地的,Maven仓库之外的类库文件 |
maven具备传递性依赖机制,maven会解析各个直接依赖的POM。下面是一个例子,最左边的一列表示A对B的依赖范围,最上面是B对C的依赖范围,那么A对C的依赖范围:
- | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | - | - | runtime |
test | test | - | - | test |
provided | provided | - | provided | provided |
runtime | runtime | - | - | runtime |
依赖调节:A和B依赖同一构件的不同版本,而C依赖同时依赖A和B,那么C对于同一构件的不同版本将出现冲突,两种解决方式:
- 短路优先:如果A–>B–>C–>X.jar,然后A–>D–>X.jar,那么后者优先解析;
- 声明优先:如果路径的长度相同,那么谁先声明就先解析。
归类依赖:最常见的就是版本号<version>
配置。
1.2 仓库
仓库:远程仓库可以在代码中进行手动配置,并且可以配置多个,比如:
<!-- 配置spring 仓库 ,用于下载中央仓库、私服 全部都找不到某个jar -->
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
- 本地仓库:Maven它一般默认本地仓库地址为用户的C盘(比如
C:\Users\liuwg-a\.m2\repository
),一般需手动更改。 - 中央仓库为:https://repo.maven.apache.org/maven2,在
%M2_HOME%\lib\maven-model-builder-3.3.9.jar
中,里面的pom文件中可以看到,maven工程的文件架构定义也可以看到。 - 私服:给局域网内的用户使用,稳定性高。
- 远程仓库:当中央仓库无法满足需求时,可以配置额外的远程仓库,可以配置多个,认证信息放置在settings.xml中的
<server>
标签中:
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
镜像仓库:即中央仓库的镜像(中央仓库里有的镜像仓库都有),比如阿里云的镜像库,通常国内的散户基本都会去配:
<mirror>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
常用的Maven仓库搜索服务提供网站(可以用于搜索依赖或者直接下载jar包)有:mvnrepository和Nexus Repository Manager。
1.3 声明周期和插件
Maven的生命周期包含了项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等构建步骤,这些构建工作都是通过maven的插件去完成的。
三套生命周期:clean(清理项目)–>default(构建项目)–>site(建立项目站点)
阶段:每个生命周期中包含一些阶段(阶段有序,后面的阶段对前面的阶段是有序的)。
- clean生命周期的阶段:pre-clean–>clean–>post-clean
- defalut声明周期的阶段主要有(很多,只写一部分):process-source(处理项目主资源文件)–>compile–>process-test-sources–>test-compile–>test–>package–>install(将包安装到本地仓库)–>deploy(将包复制到远程仓库)
- site生命周期阶段:pre-site–>site–>post-site–>
各个生命周期是相互独立的,生命周期中的各个阶段是前后依赖关系的。
插件目标:多个功能聚集在一个插件中,每个功能就叫一个插件的功能目标。
maven-dependency-plugin
插件绑定:将插件的目标和生命周期的阶段绑定完成指定的构建任务,maven中很多已经做了内置绑定。
插件<plugins>
在<build>
标签中,比如:
<!-- 插件 -->
<plugins>
<!-- 将本插件的run 目标绑定到 maven 的 default 生命周期的package 阶段 -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>当前使用的jdk 版本:${java.version}</echo>
<echo>当前使用的字符集:${project.reporting.outputEncoding}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
插件配置:
1.4 聚合与继承
聚合:为了解决多模块的构建问题,引入打包方式为POM的项目,声明任意数量的<module>
实现聚合,注意目录结构的分配,可以快速构建多个模块,每个模块其实有点像在写SDK,通过Maven打包后,在本项目中其他模块直接引入这个依赖即可。
继承:为了解决依赖重复的问题,可继承的pom元素:groupIp,version,distributionManagement,properties,dependency。
为了避免子pom引入父pom无关的依赖引入<dependencyManagement>
标签,仅仅是声明,是否真的引入由子pom决定
依赖管理:
<profiles>
用于环境的配置
1.5 Maven的环境配置
对于免安版本的maven,解压到对应的磁盘下后,需要:
1.做系统环境变量的配置:添加变量M2_HOME
,值为解压根目录比如D:\Program Files\Maven\apache-maven-3.5.4
,然后将maven的命令添加到Path
中,值为%M2_HOME%\bin
,这时基本可以,进入cmd,mvn -v
验证即可。
2.修改maven基本配置文件settings.xml
:国内基础配置改两块,一块修改本地仓库位置(默认是C盘,如C:\Users\liuwg-a\.m2\repository
),找到<settings>
标签,在里面添加(具体位置可以自己指定):
<localRepository>D:\Program Files\Maven\maven_repository</localRepository>
修改中央仓库的镜像位置(在<mirrors>
标签内部):
<mirror>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
3.注意,在IDEA中每次创建它都会去C:\Users\liuwg-a\.m2
这个用户目录下找maven的配置文件,如果找不到直接给你把拉下来的jar包塞到这个目录下的repository
文件夹下,为了避免反复手动修改的IDEA中maven的配置文件位置,在第2步中修改好的配置文件最好也往C:\Users\liuwg-a\.m2
目录下丢一份,很关键!
1.6 指定打包后jar的名字
maven打包项目时配置打包后的文件名:
<build>
<finalName>projectName</finalName>
</build>
此时maven在package后出来的jar名字就是上面配置的projectName.jar
。
如果没有上述的配置,maven默认使用pom顶部信息打包:
<groupId>com.hhu</groupId>
<artifactId>springdata</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
如果没有配置<fileName>
标签,那最终打包出来的文件名为springdata-1.0-SNAPSHOT.jar
,这个名字也是我们最常见到的jar名字。
1.7 查看maven有效配置
在配置setting.xml文件时,不确定仓库、仓库镜像、服务连接用户名和密码是否配置生效,此时可以使用命令:mvn help:effective-settings
查看有效配置。