Maven 的基础概念

Maven 是用来管理工程的一个软件,参与管理开发测试部署的整个生命周期。

Maven 安装目录

332.jpg

上面就是 Maven 的安装目录:

  • bin 是 Maven 的可运行文件,是一些运行配置文件和 cmd 的 shell 脚本。

  • boot 是 Maven 的类加载器,负责加载自己本身和管理的各种类。

  • conf 是 Maven 的所有配置文件保存地。

  • lib 是保存写 Maven 的 Java 程序需要的外部库 Jar 包保存的地方。

  • 剩下的 LICENCE 和 NOTICE 就都是证书和注意事项了。

资源坐标

描述 Maven 仓库中资源的位置,也就是一个 Jar 包的唯一描述符。

通过下面的三个标签唯一的确定一个 Jar 包资源:

1
2
3
<groupId>所属于组织的名称,一般用域名反写标识</groupId>
<artifactId>代码包的单独名称</artifactId>
<version>代码包的单独版本</version>

Maven 操作基本命令

Maven 的命令通过 shell 脚本 mvn 来执行命令,脚本 mvn 进行各种环境验证,通过后调用 JVM 运行使用 Java 编写的 Maven 主程序执行命令。

  • mvn compile 将符合 Maven 项目目录的源码和测试代码编译成字节码,并放到 Target 目录里面。
  • mvn clean 删掉生成的编译文件 Target
  • mvn test 运行所有的测试程序,根据 Assert 的断言结果,生成测试报告。
  • mvn package 执行 compile test,都通过之后,将代码打成 jar 包放到 target 目录下面。
  • mvn install 执行 compile test 通过之后,将代码打包 jar 并放置在 Maven 管理的本地仓库中。

Maven 管理的生命周期与插件

生命周期

这里指的是一个项目构建的完整生命周期的不同阶段,主要分为比较大的 clean default site 三个阶段,其中最重要的 defualt 阶段

  • clean

负责初始清理工作:pre-clean,clean,post-clean。

  • default

核心工作,编译测试打包部署,在要执行生命周期的某个事件的时候,必须从头开始一直执行到对应的位置。

332.jpg

  • site 产生报告,发布站点。

插件

插件是用来拓展在某个生命周期的阶段,所能做的事情的。插件也是 Java 代码写的,也需要唯一资源标识来引入 Jar 包,唯一不同的是配置在生命周期的执行阶段和执行内容。

<goal> 里面添加执行内容。<phase> 执行插件在哪个生命周期阶段执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<goal>jar</goal><!--执行内容是啥-->
</goals>
<phase>package</phase><!--在哪个阶段执行插件-->
</execution>
</executions>
</plugin>
</plugins>

比如下图,在生命周期的不同阶段可以激活不同的插件完成不同的工作,然后获得各种输出,比如 war jar xml 文档 等插件执行的结果。

333.jpg

依赖管理

依赖声明

用来声明项目需要依赖的代码库,会自动从仓库中下载并配合 IDEA 添加依赖。

1
2
3
4
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<scope></scope>

依赖代码状态以及打包的范围:

scope 使用范围 例子
compile (默认)主程序,测试,打包都需要 commons-logging
test 测试和打包会用到,但是主程序用不了 junit
runtime 只有打包的时候会用到,主程序和测试不用 mysql
provided 主程序和测试程序可以用,但是不会打包,服务器自带的 servlet-api

依赖传递

正是有了依赖传递,出现了间接依赖的情况:

  • 直接依赖:在当前模块中的 pom.xml 中直接加入的外部库依赖文件,被成为直接依赖,可以被使用。
  • 间接依赖:项目依赖的其他外部库所依赖的文件,可以传递给当前项目使用,不需要在 pom.xml 中声明。

依赖冲突裁决规则

对于一个依赖,项目中有大量的不同版本,那么遵循以下调用顺序:

  1. 路径优先:对于两个相同依赖的不同版本,对于当前项目进行依赖传递路径遍历,哪个版本的距离更近,选用哪一个
  2. 声明优先:对于向同级距离的间接依赖来说,所属的直接依赖,谁在前面谁优先。
  3. 后来优先:对于直接依赖的版本来说,在后面添加依赖的优先。

334.jpg

依赖传递控制

可以控制依赖传递特性是否发生,主项目可以控制自己的依赖是否将间接依赖传递过来,也可以控制自己是否将自己的依赖暴暴露给依赖他的项目。

  • 隐藏依赖:将当前项目部分依赖文件隐藏,无法被依赖当前项目的父项目看到并进行间接依赖访问。只需要在项目依赖中添加 <optional>true</optional> 即可。
1
2
3
4
5
6
7
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
<optional>true</optional> <!--引用自己的项目就看不到依赖传递过去的 junit 了-->
</dependency>
  • 断开依赖:主动隐藏/屏蔽直接依赖中传递过来的间接依赖,在本项目的依赖声明里面,添加 想要断开的间接依赖的唯一标识(不包括版本号,会断开所有的版本的间接依赖)
1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
<exclusions>
<exclusion> <!--排除依赖 junit 传过来的依赖 log4j-->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-spring-cloud-config-client</artifactId>
</exclusion>
</exclusions>
</dependency>

多项目管理

聚合管理

对于一个项目的多个模块,如果可以一起进行管理,一键所有模块一起编译测试打包,那该多是一件美事!这个 Mavan 当然可以做到啦!

首先建立一个空的项目来管理子项目,在空项目的 pom.xml 文件中,标记 <packaging> 为 pom 管理文件,然后添加 <module> 来标注自己管理的模块:

1
2
3
4
5
6
7
<packaging>pom</packaging>

<modules>
<module>../Module01</module>
<module>../Module02</module>
<module>../Module03</module>
</modules>

好了,现在对与管理模块的任何操作,都是对它包括的所有 modules 共同的操作了。

配置继承

对于多个模块有着相同的配置约束,可以写到一个模块的 pom.xml ,然后其他模块的 pom.xml 引用这个父配置文件,实现父配置文件对下属模块的配置统一管理。

父配置文件可以配置下面的东西给子模块配置继承:

335.jpg

然后子项目只需要再 <parent> 中写上父项目的唯一资源标识符,就可以继承上面的配置了。比较常用的就是 <dependencyManagement> 中规定不同组件的版本号,然后版本号就可以被子项目配置文件继承,不需要再写具体版本信息了,直接继承父项目配置文件中的。

1
2
3
4
5
6
7
<parent>
<groupId>space.xorex</groupId>
<artifactId>Manage</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../Manage/pom.xml</relativePath>
<!--这个非常重要,是父项目 pom.xml 相对路径地址-->
</parent>

属性

属性就是可以获取某些值的变量,可以通过 ${属性名} 来取出来值:

  • 自定义属性值:
1
2
3
4
5
6
7
8
9
10
11
<properties>
<junit.version>4.13</junit.version><!--在这里定义属性-->
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

主要可以用来规范

  • 内置属性:

Maven 内置的一些固定属性,如 ${basedir} ${version} 等,可以直接用。

  • Java 系统属性:

可以读取的 Java 本身的一些信息,通过 user 头获取,如 ${user.XXX}

  • 环境变量属性:

可以获取系统环境的一些属性值,通过 env 头获取:${env.XXX}

多环境兼容

对于生产测试发布不同的环境来说,使用的配置信息可能是不同的,就需要对每一种情况进行预设的配置信息管理,这就是 Maven 的多环境兼容。主要就是在 <profiles> 中添加唯一 <id><profile>。然后就可以在里面增加很多这个环境下,独有的一些属性和配置。

当我们执行命令制定了生产环境的 id 的时候,就会生效此 <profile> 里面定义的各种配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<profiles>
<profile>
<id>Development</id> <!--两套环境开发和测试-->
<properties> <!--此环境下的生效属性值-->
<now.properties>Development</devep.properties>
</properties>
<dependencies>
<dependency> <!--此环境下才需要的依赖-->
<groupId>XXXX</groupId>
<artifactId>XXX</artifactId>
<version>XXX</version>
</dependency>
</dependencies>
</profile>

<profile>
<id>Test</id>
<properties>
<now.properties>Test</devep.properties>
</properties>
<dependencies>
<dependency>
<groupId>XXXX</groupId>
<artifactId>XXX</artifactId>
<version>XXX</version>
</dependency>
</dependencies>
</profile>
</profiles>

私人 Maven 服务器

这里使用的是 Nexus,使用 bin 中的 nexus.exe /run nexus 命令启动,在 localhost:8081 默认地址打开。

可以在 etc/nexus-defualt.propertie 来修改基础的配置,在 bin/nexus.vmoptions 中修改 Java 写的服务器本身的 JVM 参数来改变服务器本身。

启动私服之后,可以创建不同的仓库用来放不同的 Jar 包,然后将这些仓库都添加到 maven-public 组里面,这样 Jar 包放到不同的仓库中,但是在同一个组中获取。

然后就是在 Maven 的配置文件中,修改 Jar 包上传和获取的地址。

首先是设置上传的服务器,设置了两个,一个是快照仓库一个是发行仓库:

1
2
3
4
5
6
7
8
9
10
11
12
<servers>
<server>
<id>XOREX-SNAPSHOT</id>
<username>root</username>
<password>1e4b489a-bf28-41ae-a46e-073ea9c5119e</password>
</server>
<server>
<id>XOREX-RELEASE</id>
<username>root</username>
<password>1e4b489a-bf28-41ae-a46e-073ea9c5119e</password>
</server>
</servers>

然后在项目的 pom.xml 中指定当前项目 deploy 的时候,上传到哪一个服务器上面:

1
2
3
4
5
6
7
8
9
10
11
<distributionManagement>
<repository>
<id>XOREX-RELEASE</id>
<url>http://localhost:8081/repository/XOREX-RELEASE/</url>
</repository>

<snapshotRepository>
<id>XOREX-SNAPSHOT</id>
<url>http://localhost:8081/repository/XOREX-SNAPSHOT/</url>
</snapshotRepository>
</distributionManagement>

然后就是配置获取 Jar 包的地址,原本我们配置了一个 <mirrors> 用来从阿里云中获取 center 服务器的镜像 Jar,现在我们要多设置一个自己的私服,从上面获取自己团队编写的 Jar 包:

1
2
3
4
5
6
7
8
</mirrors>
<mirror>
<id>XOREX-GROUP</id>
<mirrorOf>*</mirrorOf>
<name>XOREX-GROUP</name>
<url>http://localhost:8081/repository/XOREX-GROUP/</url>
</mirror>
</mirrors>

然后运行到 Deploy,就会把代码发行到私服上面了QAQ。

Maven 大概就告一段落了……