Maven - 进阶
# 分模块开发与设计
分模块视频:https://www.bilibili.com/video/BV1Ah411S7ZE?p=15
一个 Maven 项目(父 Maven)支持多个 Maven 子项目,类似一个文件夹下有多个子文件夹,那么 pom.xml 应该有多少个?
有多少个 Maven 项目,就有多少个 pom.xml 文件,其中父 Maven 的 pom.xml 管理多个子 Maven 的 pom.xml(继承)。
# 聚合
作用:聚合用于快速构建 Maven 工程,一次性构建多个项目 / 模块。
制作方式:创建一个空模块,打包类型定义为 pom,开启聚合
<packaging>pom</packaging>
定义当前模块进行构建操作时关联的其他模块名称
<modules>
<module>模块地址</module>
<module>模块地址</module>
<module>模块地址</module>
<module>模块地址</module>
</modules>
2
3
4
5
6
注意:参与聚合操作的模块最终执行顺序与模块间的依赖关系有关,与配置顺序无关。
聚合不一定要求 module
的项目在聚合项目文件夹的里面。
从图我们可以看出,聚合仅仅是创建一个仅有 pom 文件的空白项目,然后在其 pom 文件引入其他项目的路径,这样运行该空白项目时,自动找到所有的其他项目进行运行。
# 继承
作用:通过继承可以实现在子工程中沿用父工程中的配置(与 Java 类似)。
制作方式:在子工程中生命其父工程坐标与对应的位置
<!-- 子工程内容 -->
<!-- 定义该工程的父工程 -->
<parent>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- 填写父工程的 pom 文件 -->
<relativePath>父工程 pom 文件地址</relativePath>
</parent>
2
3
4
5
6
7
8
9
在父工程中定义依赖管理
<!-- 父工程内容 -->
<!-- 声明此处进行依赖管理 -->
<dependencyManagement>
<!-- 具体的依赖 -->
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependency>
</dependencies>
</dependencyManagement>
2
3
4
5
6
7
8
9
10
11
12
继承依赖使用:在子工程中定义依赖关系,无需声明依赖版本,版本参照父工程中依赖的版本
<!-- 子工程内容 -->
<dependencies>
<dependency>
<groupId></groupId>
<artifactId></artifactId>
</dependency>
</dependencies>
2
3
4
5
6
7
注意:dependencyManagement
只是管理依赖,当前工程并不会使用依赖,真正使用依赖的是子工程,子过程向父工程请求依赖。
好处:当多个子工程同时使用一个依赖,那么当该依赖要更新版本时,只需要在父工程更新版本,子工程同步更新,不需要每个子工程都去修改版本。
# 继承与聚合
作用:聚合用于快速构建项目,继承用于快速配置。
相同点:
聚合与继承的 pom.xml 文件打包方式均为 pom,可以将两种关系制作到同一个 pom 文件中
聚合与继承均属于设计型模块,并无实际的模块内容
不同点:
聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
# 属性
当多个依赖同时使用一个长内容的时候,我们可以把该内容放在一个「变量」里,然后多个依赖使用该变量即可,如版本号。
自定义属性
作用:等同于定义变量,方便统一维护。
定义格式:
<!-- 定义自定义属性 -->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
2
3
4
5
调用格式:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
2
3
4
5
内置属性
作用:使用 Maven 内置属性,快速配置。
调用格式:
${basedir} # 项目根目录
${version} # 项目版本号
2
Setting 属性
作用:使用 Maven 配置文件 setting.xml 中的标签属性,用于动态配置。
调用格式:
${settings.localRepository}
Java 系统属性
作用:读取 Java 系统属性。
调用格式:
${user.home}
系统属性查询方式
调用格式:
mvn help:system
环境变量属性
作用:使用 Maven 配置文件 setting.xml 中的标签属性,用于动态配置。
调用格式:
${env.JAVA_HOME}
环境变量属性查询方式:
mvn help:system
# 版本管理
SNAPSHOT(快照版本)
项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫快照版本(测试阶段版本)。
快照版本会随着开发的进展不断更新。
RELEASE(发布版本)
项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本。
如果使用过 Spring,就经常看到 xxx.RELEASE
。
版本约定规范
<主版本>.<次版本>.<增量版本>.<里程碑版本>
主版本:表示项目重大架构的变更,如 Spring5 相较于 Spring4 的迭代
次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
增量版本:表示有重大漏洞的修复
里程碑版本:表明一个版本的里程碑(版本内部)。这样的版本同下一个正式版本相比,相对来说不是很稳定,有待更多的测试
范例:5.1.9.RELEASE。
# 资源配置
我们利用属性可以在 pom 文件解决内容一次修改,处处生效的问题,那么对 pom 文件外面的内容呢,如我们把 jdbc 的用户名、密码等信息放在了 jdbc.properties 文件里,那么 pom 如何读取该内容呢?
用到资源配置。
作用:在任意配置文件中加载 pom 文件中定义的属性。
调用格式:
${地址}
${jdbc.url}
2
开启配置文件加载 pom 属性
<!-- 配置资源文件对应的信息 -->
<resources>
<resource>
<!-- 设定配置文件对应的位置目录,支持使用属性动态设定路径 -->
<directory>地址</directory> <!-- 如:${project.basedir}/src/main/resources -->
<!-- 开启对配置文件的资源加载过滤 -->
<filtering>true</filtering>
</resource>
</resources>
2
3
4
5
6
7
8
9
# 多环境开发配置
格式
<!-- 创建多环境 -->
<profiles>
<!-- 定义具体的环境:生产环境 -->
<profile>
<!-- 定义环境对应的唯一名称 -->
<id>开发环境名称 1</id> <!-- 如:pro_env -->
<!-- 定义环境中的专用的属性值 -->
<properties>
<jdbc.url>jdbc 链接</jdbc.url> <!-- 如:jdbc:mysql://127.1.1.1:3306/maven_db -->
</properties>
<!-- 设置默认启动 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 定义具体的环境:开发环境 -->
<profile>
<!-- 定义环境对应的唯一名称 -->
<id>开发环境名称 2</id> <!-- 如:dev_env -->
<!-- 定义环境中的专用的属性值 -->
<properties>
<jdbc.url>jdbc 链接</jdbc.url> <!-- 如:jdbc:mysql://127.2.2.2:3306/maven_db -->
</properties>
</profile>
</profiles>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
默认会找到 activation
的环境运行,如果使用开发环境名称 2,则在执行 Maven 的时候,指定环境:
mvn 指令 –P 环境定义id
例如:
mvn install –P pro_env
# 跳过测试
跳过测试环节的场景:
整体模块功能未开发
模块中某个功能未开发完毕
单个功能更新调试导致其他功能失败
快速打包
......
使用命令跳过测试
mvn 指令 –D skipTests
指令就是 install
、compile
、package
等。
注意事项:执行的指令,其生命周期必须包含测试环节。
使用界面跳过测试
如在 test 环节跳过测试(本身就是测试🤣):
使用插件跳过测试
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests> <!-- 设置跳过测试 -->
<includes> <!-- 包含指定的测试用例 -->
<include>**/User*Test.java</include> <!-- ** 任何任意包下 -->
</includes>
<excludes> <!-- 排除指定的测试用例 -->
<exclude>**/User*TestCase.java</exclude> <!-- ** 任何任意包下 -->
</excludes>
</configuration>
</plugin>
2
3
4
5
6
7
8
9
10
11
12
13
# 私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务器,私服代理广域网上的远程仓库,供局域网内的 Maven 用户使用。我们去访问这个服务器,这台服务器将需要的构件返回给我们,这台服务器中如果也没有我们需要的构件,那么这个代理服务器会去远程仓库中查找,然后将其先下载到代理服务器中,然后再返回给我们本地的仓库。我们可以也将本地的构件发布到 Nexus 中。
私服用到 Nexus,Nexus 是 Sonatype 公司的一款 Maven 私服产品。
# 下载与启动
私服下载:
https://help.sonatype.com/repomanager3/download
下载后运行,进入安装目录的 bin 目录:
进入命令行执行命令启动:
nexus.exe /run nexus
访问 http://localhost:8081
即可访问到启动的 nexus。
如果想自定义端口号或者其他,则打开 nexus 下的 etc 目录,打开 nexus-default.properties
文件,修改端口号:
如果想修改服务器的配置,则在根目录下的 bin 目录,打开 nexus.vmoptions 文件,例如修改占用内存空间。
如果是 Linux 下载,则下载命令:
wget http://sonatype-download.global.ssl.fastly.net/nexus/3/nexus-3.6.0-02-unix.tar.gz
如果是 Docker 下载,则下载命令:
docker pull sonatype/nexus3
# 仓库分类
宿主仓库 hosted:
保存无法从中央仓库获取的资源
自主研发
第三方非开源项目
代理仓库 proxy
- 代理远程仓库,通过 nexus 访问其他公共仓库,例如中央仓库
仓库组 group
将若干个仓库组成一个群组,简化配置
仓库组不能保存资源,属于设计型仓库
登录中央仓库,用户名固定是 admin
,密码自动生成,在 sonatype-work/nexus3 目录的 admin.password
文件里。
proxy:这是代理方式,它是用来代理中央仓库的,例如我们依赖的包在本地仓库没有,就会到私服获取,私服没有的话,会到中央仓库先把包下载到这里,然后再下载到本地仓库。
hosted:指的是我们公司或团队内部的包,并且 hosted 类型的仓库会分为 releases 和 snapshots 两个,前者是正式版,后者一般是开发测试版。
group:它的目的就是把多个仓库组合起来,然后我们项目中只需要配置上这个类型的仓库地址,就可以把它里面组合的几个仓库都关联上。
# 上传与下载
实际开发中,我们利用 IDEA 打包上传到本地,本地上传到私服;如果下载 jar 包,则本地去私服下载,然后给 IDEA。
所以我们需要三步:
- 配置访问私服的用户名和密码
- 本地上传到私服的仓库位置
- 本地下载 jar 包时,下载的仓库位置
- 首先配置访问私服的用户名和密码,打开 Maven 根目录下的 conf 目录下的 settings.xml,找到
servers
节点,添加如下内容:
<servers>
<server>
<id>kbt-release</id>
<username>admin</username>
<password>admin1234</password>
</server>
<server>
<id>kbt-snapshots</id>
<username>admin</username>
<password>admin1234</password>
</server>
</servers>
2
3
4
5
6
7
8
9
10
11
12
请注意上面的 id,一会儿在 pom 文件中还会用到。
- 继续找到
mirrors
节点配置私服的地址:
<mirrors>
<!-- 其他仓库如阿里云 -->
<mirror>
<id>nexus-kbt</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
2
3
4
5
6
7
8
*
代表任意仓库。下载 jar 包时,仓库的寻找自上而下,如果上面的仓库找不到,则往下面的仓库继续寻找。
在 settings.xml 文件配置的仓库是针对全部项目,如果打算在某一个项目中配置仓库,只需要在 pom 文件中加入以下配置即可
<repositories>
<repository>
<id>maven-public</id>
<name>maven-public</name>
<url>http://localhost:8081/repository/maven-public/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
2
3
4
5
6
7
8
9
10
- 接着在项目的 pom.xml 文件配置私服的地址:
<distributionManagement>
<repository>
<id>kbt-release</id>
<url>http://localhost:8081/repository/kbt-release/</url>
</repository>
<snapshotRepository>
<id>kbt-snapshots</id>
<url>http://localhost:8081/repository/kbt-snapshots/</url>
</snapshotRepository>
</distributionManagement>
2
3
4
5
6
7
8
9
10
注意:id 要对应上 settings.xml 配置的 id。
我们看到其中配置了一个 repository ,另外还有一个 snapshotRepository,上面表示的是 releases 版。同样注意 id 要和 setting.xml 里 server 下的 id 一致,不然会出现权限问题。url 分别指定 maven-releases 和 maven-snapshots 的地址。
只要在项目中配置 1.0-SNAPSHOT 这样,带有 SNAPSHOT 的就会到 snapshots 仓库,如果不加 SNAPSHOT 就会到 releases 仓库。
还有要注意的是,要发布的包不应该是上级,也就是不能有 parent 依赖。否则在获取依赖的时候会有问题。
最后发布到私服命令:
mvn deploy
或者利用 IDEA 的界面上传: