《Maven高级应用:继承聚合设计与私服Nexus实战指南》

一、 Maven的继承和聚合

1.什么是继承

Maven 的依赖传递机制可以一定程度上简化 POM 的配置,但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本,且这些模块之间不存在依赖关系,这就导致同一个依赖需要在多个模块中重复声明,这显然是不可取的,大量的前人经验告诉我们,重复往往意味着更多的劳动和更高的潜在风险

在 Java 面向对象中,我们可以建立一种类的父子结构,然后在父类中声明一些字段和方法供子类继承,这样就可以一定程度上消除重复,做到 "一处声明,多处使用"。在 Maven 的世界中,也有类似的机制,它就是 POM 继承。

Maven 在设计时,借鉴了 Java 面向对象中的继承思想,提出了 POM 继承思想。当一个项目包含多个模块时,可以在该项目中再创建一个父模块,并在其 POM 中声明依赖,其他模块的 POM 可通过继承父模块的 POM 来获得对相关依赖的声明。

对于父模块而言,其目的是为了消除子模块 POM 中的重复配置,其中不包含有任何实际代码,因此父模块 POM 的打包类型(packaging)必须是 pom。

如图所示:

子工程可以继承的父工程的元素:

|------------------------|---------------------------------|
| 元素 | 描述 |
| groupId | 项目组 ID,项目坐标的核心元素 |
| version | 项目版本,项目坐标的核心元素 |
| description | 项目的描述信息 |
| organization | 项目的组织信息 |
| inceptionYear | 项目的创始年份 |
| url | 项目的 URL 地址 |
| developers | 项目的开发者信息 |
| contributors | 项目的贡献者信息 |
| distributionManagement | 项目的部署配置 |
| issueManagement | 项目的缺陷跟踪系统信息 |
| ciManagement | 项目的持续集成系统信息 |
| scm | 项目的版本控制系统信息 |
| mailingLists | 项目的邮件列表信息 |
| properties | 自定义的 Maven 属性 |
| dependencies | 项目的依赖配置 |
| dependencyManagement | 项目的依赖管理配置 |
| repositories | 项目的仓库配置 |
| build | 包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等 |
| reporting | 包括项目的报告输出目录配置、报告插件配置等 |

父工程示例:

父工程啥也不干,里面只要pom.xml文件即可

复制代码
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode</groupId>
<artifactId>maven_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式必须是pom,声明是父工程-->
<packaging>pom</packaging>

<!--聚合子模块-->
<modules>
  <module>maven_son</module>
  <module>maven_web</module>
</modules>

<properties>
  <!--定义属性,便于版本的管理-->
  <spring-version>5.3.24</spring-version>
  <servlet-version>4.0.1</servlet-version>
</properties>

<!--只是定义,并没有真正的添加依赖,子工程根据需要有选择的添加依赖-->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <!--引用定义好的属性-->
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet-version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<build>
  <pluginManagement>
    <plugins>
      <!--只定义Tomcat插件 -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>8089</port>
          <url>/</url>
        </configuration>
      </plugin>
    </plugins>
  </pluginManagement>
</build>

子工程示例:

复制代码
<modelVersion>4.0.0</modelVersion>
<parent>
  <groupId>com.bjpowernode</groupId>
  <artifactId>maven_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
</parent>
<!--可以省略groupId和version,因为与父工程保持一致-->
<artifactId>maven_web</artifactId>
<packaging>war</packaging>

<!--需要什么依赖,添加什么依赖,可以省略版本号,版本由父工程统一管理 -->
<dependencies>
  <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  </dependency>
  <dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  </dependency>
</dependencies>

<build>
  <plugins>
    <!--配置Tomcat插件 -->
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
      <!--子工程可以自定义端口号,不自定义使用父工程的-->
      <configuration>
        <port>8060</port>
        <url>/</url>
      </configuration>
    </plugin>
  </plugins>
</build>

总结:一句话,通过继承可以实现子工程沿用父工程的配置。大大减少重复设置。

2. 什么是聚合

使用 Maven 聚合功能对项目进行构建时,需要在该项目中额外创建一个的聚合模块,然后通过这个模块构建整个项目的所有模块。聚合模块仅仅是帮助聚合其他模块的工具,其本身并无任何实质内容,因此聚合模块中只有一个 POM 文件,不包含 src 等目录。

与父模块相似,聚合模块的打包方式(packaging)也是 pom,用户可以在其 POM 中通过 modules 下的 module 子元素来添加需要聚合的模块的目录路径。父模块的 pom.xml 文件的 <modules> 把子模块聚集起来.

项目结构:

代码示例:

复制代码
<modelVersion>4.0.0</modelVersion>

<groupId>com.bjpowernode</groupId>
<artifactId>maven_ju</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
  <module>../maven_02</module>
  <module>../maven_03</module>
  <module>../maven_01</module>
  <module>../maven_parent</module>
</modules>

代码结构:

总结:一句话,聚合就是集中构建项目的。

二、 Maven的私服

1.什么是私服

私服约等于镜像

Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。

Maven 私服其实并不是 Maven 的核心概念,它仅仅是一种衍生出来的特殊的仓库,但这并不代表它不重要,相反由于私服具有降低中央仓库负荷、节省外网带宽、以及提高项目稳定性等优点,使得私服在实际开发过程中得到了相当普遍地使用。建立了 Maven 私服后,当局域网内的用户需要某个构件时,会先请求本地仓库,若本地仓库不存在所需构件,则请求 Maven 私服,将所需构件下载到本地仓库,若私服中不存在所需构件,再去请求外部的远程仓库,将所需构件下载并缓存到 Maven 私服,若外部远程仓库不存在所需构件,则 Maven 直接报错。

2. Maven仓库管理器Nexus

⑴.什么是Nexus

Nexus 是 Sonatype 公司发布的一款仓库(Repository)管理软件,常用来搭建 Maven 私服,所以也有人将 Nexus 称为"Maven仓库管理器"。 Sonatype Nexus 是当前最流行,使用最广泛的 Maven 仓库管理器。Nexus 分为开源版和专业版,其中开源版足以满足大部分 Maven 用户的需求。

⑵ Nexus仓库的类型

Nexus默认内置了很多仓库,这些仓库可以划分为3种类型,每种类型的仓库用于存放特定的jar包,具体说明如下:

  1. hosted:宿主仓库,部署自己的jar包到这个类型的仓库中,包括Releases和Snapshots两部分,Releases为公司内部发行版本仓库,Snapshots为公司内部测试版本仓库。
  2. proxy: 代理仓库,用于代理远程的公共仓库,如Maven中央仓库,用户连接私服,私服自动去中央仓库下载Jar包或者插件。
  3. group:仓库组,用来合并多个hosted/proxy仓库,通常用于配置自己的Maven连接仓库组。当我们下载jar包时,从仓库组中的每个仓库找一遍,找到后下载。

通俗的语言解释这三种 Maven 仓库类型:

1. Hosted 仓库(宿主仓库)

  • 相当于你自己公司的 "内部仓库"
  • 专门存放你们自己开发的 jar 包 / 模块
  • 分为两个区域:
    • Releases:正式发布版本(类似稳定版)
    • Snapshots:测试版本(每天自动生成的开发中版本)
  • 例:你开发了一个支付 SDK,正式发布到 Releases,测试版放 Snapshots

2. Proxy 仓库(代理仓库)

  • 相当于 "代购机器人"
  • 当你需要下载公共仓库(如 Maven 中央仓库)的 jar 包时
  • 私服会自动通过 Proxy 去中央仓库下载
  • 好处:公司内所有开发者都可以共享缓存,加快下载速度
  • 例:当你在 pom.xml 中引用 spring-boot-starter,私服会通过 Proxy 自动下载

3. Group 仓库(仓库组)

  • 相当于 "仓库集合管理器"
  • 把多个 hosted/proxy 仓库合并成一个逻辑组
  • 当你执行 mvn install 时,会按顺序从组内的仓库查找
  • 常见配置:把公司内部的 hosted 和代理的 central 仓库合并成一个 group
  • 例:配置成 [hosted-releases, hosted-snapshots, proxy-central] 的顺序查找

总结使用场景:

  • 发布自己的代码 → Hosted 仓库
  • 下载外部依赖 → Proxy 仓库
  • 统一配置管理 → Group 仓库
  • 最终开发者只需要连接 Group 仓库即可自动管理所有依赖

⑶如何搭建私服

下载Nexus

官网地址:https://help.sonatype.com/repomanager3/download

安装Nexus

下载后解压到一个没有中文的路径下:

进入到D:\nexus-3.66.0-02\bin目录下:

双击nexus.exe没有反应,需要以管理员身份打开cmd窗口,输入命令: nexus /run 回车,需要等待一段时间,直到出现Started Sonatype Nexus OSS 3.66.0-02说明安装成功。

访问Nexus

访问地址:http://localhost:8081

端口号可以改变,在D:\nexus-3.66.0-02\etc目录下的nexus-default.properties文件中进行修改。

3. Nexus私服的应用

⑴ 登录

密码所在的文件:

点Browse观察

⑵设置仓库

创建仓库

起名

创建

将创建好的仓库添加到public组中。

⑶ 使用Nexus下载jar包

创建一个新的本地仓库,用来接收Nexus下载下来的jar包。

因为要使用Maven工具访问私服,所以settings.xml文件要修改。

本地仓库地址修改为新地址

设置每次访问Nexus的用户名和密码,修改settings.xml文件中的<server>标签

设置<mirror>标签为Nexus的maven-public库地址(仓库组)

复制代码
	<mirror>
  <id>hhh-nexus</id>
  <mirrorOf>central</mirrorOf>
  <name>mynexus</name>
  <url>http://localhost:8081/repository/maven-public/</url>
</mirror>

其中<url>标签的地址复制maven-public库的地址。这个地址取代了中央仓库地址。我们所有的jar包下载都是从这个地址里找。它包含宿主库和代理库的所有地址。

打开Idea2023,确定是新的本地仓库地址

观察私服Nexus上的maven-public组

⑷使用Idea部署jar包到Nexus私服

私服Nexus是部署在局域网的,是全公司共享的仓库地址,每个团队都可以将已完成的功能或测试版本发布到私服供别人来使用。

打开要部署的项目的pom.xml文件,设置上传路径

复制代码
<distributionManagement>
  <repository>
    <id>hhh-nexus</id>
    <url>http://localhost:8081/repository/hhhh-release/</url>
  </repository>

  <snapshotRepository>
    <id>hhh-nexus</id>
    <url>http://localhost:8081/repository/hhh-snapshot/</url>
  </snapshotRepository>

</distributionManagement>

其中<url>路径来自于私服hhh-snapshot.

运行deploy部署命令

观察私服对应仓库变化

snapshot项目部署

release项目部署

相关推荐
想做富婆10 分钟前
python入门:不同进制数据的表示方式,转换;数据类型的转换,隐式类型的转换
开发语言·python
Littlehero_12112 分钟前
qt中关于思源雅黑字体的使用
开发语言·qt
haaaaaaarry16 分钟前
【贪心】C++ 活动安排问题
开发语言·c++·算法·贪心
Thomas_YXQ25 分钟前
Unity3D 测试驱动开发(TDD)框架设计
java·开发语言·驱动开发·全文检索·unity3d·lucene·tdd
末央&27 分钟前
【C++】深入浅出之继承
开发语言·c++
雾喔42 分钟前
库洛游戏一面+二面
java·开发语言·游戏
电子连接器CAE与高频分析5 小时前
Matlab添加标题title与标签lable
开发语言·matlab
努力弹琴的大风天5 小时前
MATLAB遇到内部问题,需要关闭,Crash Decoding : Disabled - No sandbox or build area path
开发语言·matlab
奋进的小暄6 小时前
数据结构(java)栈与队列
java·开发语言·数据结构
笺上山河梦7 小时前
文件操作(二进制文件)
开发语言·c++·学习·算法