Maven: 是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

0x01 入门

1.1 maven目录结构

  1. maven3:.
  2. LICENSE
  3. NOTICE
  4. README.txt
  5. ├─bin //mvn的运行脚本
  6. m2.conf
  7. mvn
  8. mvn.cmd
  9. mvnDebug
  10. mvnDebug.cmd
  11. mvnyjp
  12. ├─boot //类加载器框架
  13. plexus-classworlds-2.5.2.jar
  14. ├─conf //配置文件
  15. settings.xml
  16. toolchains.xml
  17. └─logging
  18. simplelogger.properties
  19. └─lib //mvn使用的类库
  20. aether-api-1.0.2.v20150114.jar
  21. aether-api.license
  22. aether-connector-basic-1.0.2.v20150114.jar
  23. ...

0x02 核心

2.1 maven命令格式

mvn [plugin-name]:[goal-name]:执行“plugin-name”插件的“goal-name”目标(或者称为动作)。

用户调用maven插件目标的两种方式:

  1. 将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因此命令mvn compile实际上是先定位到compile这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的compile目标。
  2. 直接在命令行指定要执行的插件目标,例如mvnarchetype:generate 就表示调用maven-archetype-plugin的generate目标,这种带冒号的调用方式与生命周期无关。

2.2 maven常用命令

Maven命令列表
mvn –version 显示版本信息
mvn clean 清理项目生产的临时文件,一般是模块下的target目录
mvn compile 编译源代码,一般编译模块下的src/main/java目录
mvn package 项目打包工具,会在模块下的target目录生成jar或war等文件
mvn test 测试命令,或执行src/test/java/下junit的测试用例.
mvn install 将打包的jar/war文件复制到你的本地仓库中,供其他模块使用
mvn deploy 将打包的文件发布到远程参考,提供其他人员进行下载依赖
mvn site 生成项目相关信息的网站
mvn eclipse:eclipse 将项目转化为Eclipse项目
mvn dependency:tree 打印出项目的整个依赖树
mvn archetype:generate 创建Maven的普通java项目
mvn tomcat:run 在tomcat容器中运行web应用
mvn jetty:run 调用 Jetty 插件的 Run 目标在 Jetty Servlet 容器中启动 web 应用

注意:运行maven命令的时候,首先需要定位到maven项目的目录,也就是项目的pom.xml文件所在的目录。否则,必以通过参数来指定项目的目录。

命令参数
上面列举的只是比较通用的命令,其实很多命令都可以携带参数以执行更精准的任务。

Maven常用命令参数列表
-D 传入属性参数
mvn package -Dmaven.test.skip=true以“-D”开头,将“maven.test.skip”的值设为“true”,就是告诉maven打包的时候跳过单元测试。同理,“mvn deploy-Dmaven.test.skip=true”代表部署项目并跳过单元测试。

- -DskipTests=true:编译测试,但不运行
- -Dmaven.test.skip=true:既不编译测试,也不运行。
-P 使用指定的Profile配置
比如项目开发需要有多个环境,一般为开发,测试,预发,正式4个环境,在pom.xml中的配置如下:profiles定义了各个环境的变量id,filters中定义了变量配置文件的地址,其中地址中的环境变量就是上面profile中定义的值,resources中是定义哪些目录下的文件会被配置文件中定义的变量替换。

通过maven可以实现按不同环境进行打包部署,命令为:
mvn package -P dev
其中“dev“为环境的变量id,代表使用Id为“dev”的profile。
-e 显示maven运行出错的信息
-o 离线执行命令,即不去远程仓库更新包
-X 显示maven允许的debug信息
-U 强制去远程更新snapshot的插件或依赖,默认每天只更新一次
-T 指定构建中涉及的并行线程数。如果您的项目可以并行地构建,例如不依赖于彼此的模块,则此选项表示-T 4(使用4个线程)可以显着加速您的构建时间。
-pl
仅构建指定的模块,而不是整个项目。当您在多模块项目的一个模块中工作时,您知道您的更改将在那里本地化,因此您可能希望避免通过建立其他所有内容来完成空的工作。

2.3 maven构建项目目录骨架

maven提供的archetype插件,用于创建符合maven规定的目录骨架。 目录规定:src-main-java-主代码 /src-test-java-测试代码

maven 调用archetype命令的两种方式:

  1. mvn archetype:generate<br />运行命令后根据提示信息依次输入坐标信息(GAV)和包名:groupId,artifactId,version,package
  2. mvn archetype:generate -DgroupId:组织名,公司域名反写+项目名 -DartifactId:项目名-模块名 -Dversion:版本 -Dpackage:包名<br />一次性创建
  1. data-web:.
  2. data-web.iml
  3. pom.xml
  4. readme
  5. ├─src
  6. ├─main
  7. ├─java
  8. └─package //自定义的包
  9. └─resources
  10. └─test
  11. └─java
  12. └─package //自定义的包
  13. └─target
  14. ├─classes
  15. application.properties
  16. ...
  17. ├─package //编译生成的字节码文件(.class)
  18. └─...
  19. └─META-INF
  20. data-web.kotlin_module
  21. ├─generated-sources
  22. └─annotations
  23. ├─generated-test-sources
  24. └─test-annotations
  25. └─test-classes
  26. └─package //

2.4 maven生命周期和插件

Maven 构建生命周期定义了一个项目构建跟发布的过程。maven对生命周期的每个阶段进行了抽象,每个插件就是对每个抽象的具体实现。 一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:清理、编译、测试、打包、集成测试、验证、部署。

Maven的生命周期分为三个独立的生命周期:

  1. clean:清理项目
      • pre-clean :执行清理前的工作
      • clean:清理上一次构建生成的所有文件
      • post-clean:执行清理后的文件
  2. default:构建项目
      • compile
    1. -test
    2. -package
    3. -install
  3. site:生成项目站点
      • pre-site:在生成项目站点之前要完成的工作
      • site:生成项目的站点文档
      • post-site:在生成项目站点后要完成的工作
      • site-deploy:发布生成的站点到服务器上

Tips

  1. 每一个独立的生命周期有分为若干个阶段,其中defaul是最核心的一个;
  2. Maven的生命周期对应的命令是顺序执行的,如果没有人为的顺序的一个个执行,那么Maven会默认的自动运行;当我们从中间的某个阶段执行了的话,Maven也会自动的为当前阶段执行前面的每个阶段的。

2.5 maven pom.xml解析

POM 标签大全详解

2.6 maven依赖范围

Maven因为执行一系列编译、测试和部署运行等操作,在不同的操作下使用的classpath不同,依赖范围就是用来控制依赖与三种 classpath(编译classpath、测试classpath、运行classpath)的关系。

依赖范围(scope):
1.compile:默认范围,使用此依赖范围对于编译、测试、运行三种 classpath 都有效,即在编译、测试和运行的时候都要使用该依赖jar包
2.provided:在编译和测试时有效
3.runtime:在测试和运行时有效, 在编译主代码时无效,典型的就是JDBC驱动实现
4.test:只在测试时有效,典型的是JUnit,它只用于编译测试代码和运行测试代码的时候才需要
5.system:在编译和测试时有效,与本机系统关联,可移植性差必须通过systemPath元素显示地指定依赖文件的路径,不依赖Maven仓库解析,所以可能会造成建构的不可移植,谨慎使用
6.import:导入的范围,它只使用在dependencyManagement中,表示从其他的pom中导入dependency的配置

2.7 maven依赖传递

传递依赖:简单讲就是间接依赖关系,比如:B依赖A,C依赖B,那么C也就依赖A了,C和A的依赖关系就是传递依赖。
Maven对于依赖的管理是这样的,当在POM.XML文件中发现配置了,某个依赖,就先去自己本地的依赖仓库中去找对应的依赖,如果没找到,就去Maven的中央依赖仓库中去找,如果还是没找到,就会报错。
对于项目而言,比如上面的例子A/B/C我们需要在B的POM.XML依赖关系中配置上A的坐标,并且需要对A进行编译、打包、安装到本地仓库等工作,B才能实现对A的依赖。C依赖于B,并且B依赖于A,C的依赖库里会自动的将A项目的jar包也导进来的。如果我们不想这样,那么就需要用到排除依赖这个标签了——此标签就是排除对传递依赖的依赖关系的一种方式。

2.8 maven依赖冲突

依赖冲突原则:
1.短路优先:C依赖B,B依赖A,A和B都包含同一个不同版本的Jar,则取B的依赖版本
2.声明优先:C依赖A和B,A和B都包含同一个不同版本的Jar,谁先声明取谁的依赖版本

2.9 maven聚合和继承

聚合:
如果项目D依赖项目C,项目C依赖项目B,项目B依赖项目A,我们需要一个个安装这项项目,在Maven中有一种方式可以将多个项目一次性安装,这就是聚合的概念。简单讲就是,需要人工多次操作的,只要Maven能理解,一次性告诉他,他就能帮我们做这件单调烦人的事情了。——使用这个标签。

继承:
多次使用到的依赖,比如:单元测试,没有必要在所有的项目中都引用一下,此时就可以采用继承的方式来实现,先来一个父级的POM.XML然后再继承此POM.XML。
1. packaging 改为pom。
2. dependencyManagement 中并不提取依赖,只进行统一管理。
3. property中定义了junit版本号,之后可以引用。
4. 父类parent中的main和test没有意义,可以删除。

0x03 实战

0x04 Maven cheat sheet

maven-cheat-sheet.pdf

0x05 Preference


What is Maven
比较 Gradle,Maven和Ant
Maven Options Cheat Sheet
Maven 完整参考