maven

简介

一个项目管理工具,

  1. 服务于java平台,也是由java编码
  2. 发展:Make->Ant->Maven->Gradle

包含:

  1. 一个项目生命周期
  2. 一个Project Object Model 项目对象模型(抽象的生命周期定义)
  3. 一个依赖管理系统(具体实现生命周期)
  4. 一组标准集合
  5. 运行定义在生命周期阶段中插件目标的逻辑

用途

  1. 自动化构建工程
  2. 管理jar包
  3. 编译代码
  4. 自动运行单元测试、打包、生成报表、部署项目、生成web站点。。。

安装

  1. 保证JDK安装

  2. 环境变量

1
2
3
4
MAVEN_HOME
%MAVEN_HOME%\bin;

// 有时候使用M2_HOME为了向旧版本兼容。
  1. mvn -v

生命周期

Maven生命周期,能够自动化完成项目构建的整个过程。

常规构建过程

以java源文件、框架文件、静态资源等作为原材料,生产得到一个可运行项目。具体包括:

  1. 清理:删除旧class文件
  2. 编译:.java源文件 -> .class字节码文件(JVM可执行文件)
  3. 测试:自动测试,自动调用junit程序
  4. 报告:测试结果
  5. 打包:动态web工程打war包,java工程打jar包
  6. 安装:Maven特定概念,打包文件复制到仓库指定位置(mvn install)
  7. 部署:war包复制到指定目录,使其可运行

Maven生命周期

maven核心程序定义了抽象的生命周期(各个构建环节),生命周期的各个阶段具体依赖插件完成。

三套相互独立的生命周期,三套生命周期的命令可以相互组合,分别是:

  1. Clean Lifecycle:清理工作
    • pre-clean
    • clean:移除上一次构建文件
    • post-clean
  2. Default Lifecycle:构建核心,编译、测试、打包、安装、部署
    • validate
    • compile
    • test
    • package
    • verify
    • install
    • deploy
  3. Site Lifecycle:生成报告、站点文档、发布站点
    • pre-site
    • site:生成项目的站点文档
    • post-site
    • site-deploy:发布、部署生成的文档到特定服务器

当执行某个环节的命令时,如mvn test,其实maven会帮我们从生命周期最开始一直执行到mvn test,是个累进执行的过程。

Maven命令

通过mvn命令,执行生命周期的各个阶段。

注意:一定要在pom.xml目录下,执行Maven命令。

常见命令如下:

  1. mvn clean

  2. mvn compile

  3. mvn package

  4. mvn install: 安装

    • 把自定义的maven项目,安装至本地仓库。
  1. mvn test-compile:编译测试程序

  2. mvn test:执行测试

  1. mvn site

POM

  1. Project Object Model 项目对象模型
  2. pom.xml是maven工程的核心配置文件,配置构建过程的一切设置。

build

如果没有特殊配置,Maven会按照标准的目录结构查找和处理各种类型文件。

源代码目录 打包文件 打包目录
src/main/java 仅*.java target/classes
src/test/java 仅*.java targe/test-classes
src/main/resouces 所有文件 target/classes
src/test/resources 所有文件 target/test-classes
  1. 若将资源文件(xml,properites,xsd等)放在src/main/resources目录,maven默认把资源文件打包到相应的jar或者war里。
  2. 若将资源文件(mybatis的mapper.xml)放到src/main/java目录,则maven默认只打包java文件,而忽略.xml文件,需要在pom.xml中,进行配置

包含/排除特殊文件打包的配置方案有两种:

  1. 元素下添加进行配置。不需要任何插件。
  2. 子元素中配置maven-resources-plugin等处理资源文件的插件。
resource

**/*:是为了保证各级子目录下的资源文件被打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<build> 
<resources>

<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<!-- 处理主资源目下的资源文件时,是否对主资源目录开启资源过滤 -->
<filtering>true</filtering>
</resource>

</resources>
</build>

默认resources目录下的文件都会被打包

如果想过滤resources目录特殊文件,需要手动配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!--过滤resource下的文件-->
<build>
<resources>

<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>app/**/*</exclude>
<exclude>node/**/*</exclude>
</excludes>
</resource>

</resources>
</build>
插件

resource功能可以使用插件实现,另外,插件具有自定义资源目录等额外功能。

  1. maven-resources-plugin:资源处理插件,可添加额外的资源文件目录

  2. build-helper-maven-plugin:另一种资源处理插件

  3. maven-compiler-plugin:java代码处理插件

  4. maven-jar-plugin:target/classes目录中的一些文件不希望打入jar包中

依赖

maven核心程序只定义抽象的生命周期,具体实现需要特定的依赖。

依赖的来源

类别
  1. 本地仓库:部署在本地电脑,为本地电脑所有Maven工程服务
  2. 私服:局域网环境。私服与外网环境交流。供局域网内部使用。
    • Maven私服产品Nexus。Nexus
  3. 中央仓库:互联网,为全世界maven服务。
  4. 中央仓库镜像:分担中央仓库流量压力,提升用户访问速度。
仓库保存的内容
  1. maven所需插件
  2. 第三方框架或工具的jar包
    • 第一方是JDK,第二方是开发者
  3. 自己开发的maven工程

项目引用依赖的过程

当执行maven命令,需要某些依赖包时,

  1. 首先在本地仓库查找
    • 默认:用户电脑家目录.m2\repository
    • 自定义:\maven目录\conf\settings.xml,修改localRepository标签
1
<localRepository>E:\repository</localRepository>
  1. 本地找不到,会自动连外网到中央仓库下载
1
https://mvnrepository.com/
  1. 外网连接失败,则构建失败

定位依赖(坐标)

Maven坐标在仓库中唯一定位一个Maven工程,包括如下内容,简称gav。

  1. groupId:公司组织域名的倒序 + 项目名
  2. artifactId:模块名
  3. version:版本

一个项目可以包含多个模块,或一个项目只有一个模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
项目名与模块名相同
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
</dependency>

项目名与模块名不同
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>

Maven坐标,与仓库中的路径,一致

1
2
3
4
5
groupId / artifactId / version / artifactId-version.jar
io/springfox/springfox-swagger2/2.8.0/springfox-swagger2-2.8.0.jar

如,结合本地仓库地址:
E:\repository\io\springfox\springfox-swagger2\2.8.0\springfox-swagger2-2.8.0.jar

依赖作用范围

依赖的作用范围scope,常见取值:

  1. compile(默认)
  2. test
  3. provided

    • 相对于compile的区别:在打包阶段进行了exclude操作,不参与打包
  4. system

    • 与provided基本相同。

    • 相对于provided的区别:不从maven仓库获取,而是从本地文件系统提取,利用systemPath指定路径。

  5. import
    • maven2.0.9版本后的属性
    • 只能在dependencyManagement的中使用,解决maven单继承问题
scope 对主程序src/main是否有效 对测试程序src/test是否有效 是否参与打包
compile 有效 有效 参与
test 有效
provided 有效 有效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!-- 本地依赖统一放到项目的lib目录下-->
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.75.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/javamelody-core-1.75.0.jar</systemPath>
</dependency>

<dependencyManagement>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>

依赖传递

  1. compile范围的依赖,自动传递:父项目pom.xml配置的依赖,各个子模块自动继承,不必再次声明。

  2. 非compile范围的依赖,不能传递。

依赖排除

依赖中排除特定jar包。被排除的内容也会具有传递性,在子项目中也会被排除。

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<exclusions>
<exclusion>
<artifactId>log4j-api</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
</exclusions>
</dependency>

依赖原则

用于解决模块工程之间的jar包冲突问题:

  1. 就近原则:如果从祖父、父模块,分别继承同一个jar包不同版本,则采取就近原则,使用父模块版本号。
  2. 先声明者优先(dependency顺序):同时依赖了两个不同版本的jar包,则谁先声明谁优先。

统一管理依赖版本号

properties标签

properties标签配合自定义标签不一定仅用于版本号,可以用于其他自定义场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 统一定义 -->
<properties>
<net.version>1.3.4-SNAPSHOT</net.version>
<tomcat.version>8.5.51</tomcat.version>
<java.version>1.7</java.version>
</properties>

<!-- 调用 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>${tomcat.version}</version>
</dependency>
继承
  1. 统一在父工程配置版本【父,只负责管理版本,不负责真正下载】
  2. 在子工程中声明依赖时,不指定版本【子,负责声明所需依赖,不负责版本】

父工程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<groupId>父工程groupId</groupId>
<artifactId>父工程artifactId</artifactId>
<version>父工程版本号</version>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

子工程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 指定父工程 -->
<parent>
<groupId>父工程groupId</groupId>
<artifactId>父工程artifactId</artifactId>
<version>父工程版本号</version>

<!-- 子工程pom.xml为准的父工程pom.xml的相对路径 -->
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
聚合

使用了继承的工程,mvn 安装要先安装父工程,再安装子工程。

可以使用聚合,来一键安装所有模块的依赖。

父工程

1
2
3
4
5
6
<!-- 指定各子工程的相对路径,maven可以自动识别依赖顺序 -->
<modules>
<module>common</module>
<module>net</module>
<module>platform</module>
</modules>

自动部署

1
2
3
4
5
6
<!-- 配置构建过程中的特殊设置 -->
<build>
<!-- 配置构建过程中的使用的插件 -->
<plugins>
</plugins>
</build>

参考

  1. 生命周期:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference
  2. maven依赖:https://mvnrepository.com/
-------------Keep It Simple Stupid-------------
0%