Maven 进阶与私服架构

3. Maven 进阶

3.1 pom.xml 文件

  • 核心地位 :类比 Make 的 MakeFile、Ant 的 build.xml,是 Maven 项目的核心配置文件,基于项目对象模型(POM) 定义项目基本信息,描述构建流程、声明依赖关系等。
  • 核心作用:统一管理项目配置,包括坐标、依赖、构建插件、生命周期绑定等,确保项目构建的标准化和可复用性。

3.2 坐标

3.2.1 坐标概念
  • Maven 中构件的唯一标识,通过一组元素定位依赖或项目自身,确保在仓库中能精准找到目标构件。
3.2.2 坐标元素及要求
元素 必要性 含义 示例
groupId 必须 组织标识,通常为 "公司网址反写 + 项目名",体现项目所属组织 / 团队 cn.tx.maven(tx 为公司 / 团队标识,maven 为项目名)
artifactId 必须 项目 / 模块名称,区分同一 groupId 下的不同模块 Hello(独立模块)、HelloFriend(依赖 Hello 的模块)
version 必须 版本号,格式为 "大版本。分支版本。小版本 - 限定词" 0.0.1-SNAPSHOT(SNAPSHOT 表示快照版)、1.0-RELEASE(RELEASE 表示稳定版)
packaging 可选 打包方式,默认值为 "jar",其他常见值有 "war"(Web 项目)、"pom"(父项目) jar、war、pom
classifier 可选 描述构件附属信息,用于区分同一坐标下的不同附属构件(如源码包、文档包) sources(源码包)、javadoc(文档包)
3.2.3 坐标意义
  • 解决 "构件唯一标识" 问题,让机器可自动根据坐标查找、下载依赖,无需人工管理 JAR 包路径。

3.3 依赖

3.3.1 依赖意义
  • 解决项目对外部库(如 JUnit)或内部模块的依赖管理问题,自动处理递归依赖(如 A 依赖 B,B 依赖 C,则 A 自动获取 C),避免手动下载、复制 JAR 包的繁琐和版本冲突。
3.3.2 依赖配置格式

在 pom.xml 的 <dependencies> 标签内声明依赖,示例如下:

xml

复制代码
<dependencies>
    <!-- 第三方依赖(JUnit) -->
    <dependency>
        <groupId>junit</groupId> <!-- 组织标识 -->
        <artifactId>junit</artifactId> <!-- 依赖名称 -->
        <version>4.9</version> <!-- 版本号 -->
        <scope>test</scope> <!-- 依赖范围(仅测试时生效) -->
    </dependency>
    <!-- 内部模块依赖(Hello 模块) -->
    <dependency>
        <groupId>cn.tx.maven</groupId>
        <artifactId>Hello</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <scope>compile</scope> <!-- 默认范围,编译/测试/运行均生效 -->
    </dependency>
</dependencies>
3.3.3 第三方依赖查找方法
  1. 访问 Maven 中央仓库官网:https://mvnrepository.com/
  2. 在搜索框输入依赖名称(如 mybatis、fastjson)
  3. 选择目标依赖及对应版本,复制生成的坐标配置到 pom.xml 中

3.4 依赖范围(Scope)

3.4.1 核心作用

控制依赖在不同 classpath(主代码、测试代码、运行时) 中的生效范围,避免不必要的依赖打包或版本冲突。

3.4.2 常见依赖范围及特性
依赖范围 主代码 classpath 有效 测试代码 classpath 有效 运行时 classpath 有效 打包时包含 示例
compile Y Y Y Y log4j(项目运行全程依赖)
test N Y N N JUnit(仅测试代码用)
provided Y Y N N servlet-api(运行时由 Tomcat 提供)
runtime N Y Y Y JDBC 驱动(编译时用接口,运行时用实现)
system Y Y N N 本地非仓库的 JAR 包(需指定 systemPath,不推荐)
import - - - - 仅在 dependencyManagement 中使用,导入其他 POM 的依赖配置

3.5 依赖传递与依赖控制

3.5.1 依赖传递
  • 概念:当项目 A 依赖项目 B,项目 B 依赖项目 C 时,A 会自动继承 B 对 C 的依赖(A→B 为第一直接依赖,B→C 为第二直接依赖,A→C 为传递依赖)。
  • 示例:HelloFriend 依赖 Hello,MakeFriend 依赖 HelloFriend,则 MakeFriend 会自动依赖 Hello。
3.5.2 依赖范围对传递依赖的影响

传递依赖的生效范围由 "第一直接依赖范围" 和 "第二直接依赖范围" 共同决定,核心规则如下:

第一直接依赖范围 \ 第二直接依赖范围 compile test provided runtime
compile compile(生效) 不生效 不生效 runtime(生效)
test test(生效) 不生效 不生效 test(生效)
provided provided(生效) 不生效 provided(生效) provided(生效)
runtime runtime(生效) 不生效 不生效 runtime(生效)
3.5.3 依赖阻断(可选依赖)
  • 作用:阻止依赖传递,避免不需要的间接依赖被引入。
  • 配置方式 :在依赖中添加 <optional>true</optional>,示例:

xml

复制代码
<dependency>
    <groupId>cn.tx.maven</groupId>
    <artifactId>Hello</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <optional>true</optional> <!-- HelloFriend 依赖 Hello,但 MakeFriend 不继承 Hello -->
</dependency>
3.5.4 依赖排除(Exclusion)
  • 作用:强制排除依赖中的某个间接依赖(如解决版本冲突)。
  • 配置方式 :在依赖中添加 <exclusions> 标签,示例:

xml

复制代码
<dependency>
    <groupId>cn.tx.maven</groupId>
    <artifactId>HelloFriend</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <exclusions>
        <exclusion> <!-- 排除 HelloFriend 传递的 Hello 依赖 -->
            <groupId>cn.tx.maven</groupId>
            <artifactId>Hello</artifactId>
        </exclusion>
    </exclusions>
</dependency>

3.6 仓库

3.6.1 仓库概念与分类
  • 概念 :存储 Maven 构件(JAR、WAR、POM 等)的位置,分为三类:
    1. 本地仓库 :用户本地存储构件的目录,默认路径为 ~/.m2/repository(Windows:C:\Users\用户名\.m2\repository),首次执行 Maven 命令时自动创建。
    2. 中央仓库 :Maven 社区维护的公共仓库(http://repo1.maven.org/maven2),包含绝大多数开源 Java 构件,无需配置即可访问(需联网)。
    3. 远程仓库:企业 / 团队搭建的私有仓库(如私服)或第三方公共仓库,用于存储内部构件或代理中央仓库。
3.6.2 依赖搜索顺序
  1. 优先查找本地仓库,若存在则直接使用;
  2. 本地仓库不存在时,查找远程仓库(如私服),若存在则下载到本地仓库后使用;
  3. 远程仓库不存在时,查找中央仓库,下载到本地仓库后使用;
  4. 所有仓库均不存在时,构建失败并报错。
3.6.3 本地仓库配置
  • 全局配置 (影响所有用户):修改 %MAVEN_HOME%\conf\settings.xml,指定 <localRepository> 路径:

xml

复制代码
<localRepository>D:\maven-repository</localRepository>
  • 用户配置 (仅影响当前用户):在 ~/.m2 目录下创建 settings.xml,配置同上(优先级高于全局配置)。

3.7 生命周期

3.7.1 生命周期概念
  • Maven 对项目构建流程(清理、编译、测试、打包、部署)的标准化抽象,本身不执行具体操作,仅定义 "阶段(Phase)" 及执行顺序,具体操作由 "插件" 完成。
  • 三套独立生命周期:Clean(清理)、Default(构建)、Site(生成站点),彼此独立,可单独执行。
3.7.2 核心生命周期及阶段
生命周期 核心阶段(按执行顺序) 阶段作用 绑定的核心插件
Clean pre-clean → clean → post-clean 清理项目输出(如 target 目录) maven-clean-plugin:clean(clean 阶段)
Default validate → compile → test → package → install → deploy 编译源码→测试→打包→安装到本地仓库→部署到远程仓库 maven-compiler-plugin:compile(compile 阶段)、maven-surefire-plugin:test(test 阶段)、maven-jar-plugin:jar(package 阶段,JAR 打包)
Site pre-site → site → post-site → site-deploy 生成项目文档(如 API 文档)→部署文档到远程站点 maven-site-plugin:site(site 阶段)、maven-site-plugin:deploy(site-deploy 阶段)
3.7.3 生命周期执行规则
  • 执行某个阶段时,Maven 会自动执行该阶段之前的所有阶段 (如执行 mvn install,会依次执行 validate→compile→test→package→install);
  • 可同时执行多个阶段,按输入顺序执行(如 mvn clean package,先执行 Clean 生命周期的所有阶段,再执行 Default 生命周期到 package 阶段)。

3.9 Maven 继承与聚合

3.9.1 继承
  • 核心作用:消除多模块项目的配置重复,统一管理公共依赖、插件、仓库等,提升项目安全性和可维护性(如多个模块共用 JUnit、Spring 版本)。
3.9.2 可继承的 POM 元素
类别 可继承元素 说明
项目标识 groupId、version 子项目默认继承父项目的 groupId 和 version,无需重复配置
项目信息 description、organization、developers 项目描述、组织信息、开发者信息等公共元数据
依赖管理 dependencies、dependencyManagement dependencies:子项目自动继承依赖;dependencyManagement:子项目需显式声明依赖,但无需指定版本(继承父项目版本)
构建配置 build(源码目录、插件配置)、reporting 统一的源码路径、插件版本(如 maven-compiler-plugin)
仓库配置 repositories、pluginRepositories 子项目继承父项目的仓库地址,无需重复配置
3.9.3 IDEA 实现继承(以父项目 parent 为例)
  1. 创建父项目

    • 打包方式设为 pom(父项目仅用于管理,不生成构件):

    xml

    复制代码
    <packaging>pom</packaging>
    • 在父项目 pom.xml 中通过 <modules> 声明子模块:

    xml

    复制代码
    <modules>
        <module>core</module> <!-- 子模块 1 -->
        <module>manage</module> <!-- 子模块 2 -->
        <module>portal</module> <!-- 子模块 3 -->
    </modules>
  2. 创建子项目

    • 选择 "New Module",父项目指定为上述 parent,子项目自动继承 groupId 和 version;
    • 子项目 pom.xml 中通过 <parent> 标签关联父项目:

    xml

    复制代码
    <parent>
        <groupId>cn.tx.extends</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>core</artifactId> <!-- 子项目仅需配置 artifactId -->
3.9.4 聚合
  • 核心作用 :多模块项目中,通过 "聚合项目(父项目)" 一键执行所有子模块的构建操作(如 mvn install 父项目,会自动构建所有子模块),无需逐个模块执行命令。
  • 实现方式 :父项目通过 <modules> 标签聚合子模块,与继承共用父项目配置,实现 "一键构建 + 配置统一"。
3.9.5 properties 属性
  • 作用:定义全局变量,统一管理版本号、路径等,避免重复书写(如统一 Spring、MySQL 版本)。
  • 配置示例

xml

复制代码
<properties>
    <spring.version>5.3.20</spring.version> <!-- 定义 Spring 版本变量 -->
    <mysql.version>5.1.47</mysql.version> <!-- 定义 MySQL 版本变量 -->
</properties>
<!-- 引用变量 -->
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version> <!-- 引用 Spring 版本变量 -->
    </dependency>
</dependencies>

4. Maven 私服架构

4.1 私服介绍

4.1.1 私服概念与价值
  • 概念:企业在局域网内搭建的 Maven 远程仓库,兼具 "私有构件存储" 和 "中央仓库代理" 功能。
  • 核心价值
    1. 存储企业内部构件(如自研的工具类 JAR、业务模块),供内部项目复用;
    2. 代理中央仓库,避免所有项目直接联网下载,节省带宽并提高依赖获取速度;
    3. 控制依赖权限,确保内部构件不对外泄露,同时统一管理第三方依赖版本。
4.1.2 Nexus 介绍
  • Nexus 是主流的 Maven 仓库管理器,支持:
    • 创建多种类型仓库(宿主、代理、仓库组);
    • 可视化管理构件(上传、删除、搜索);
    • 权限控制(不同用户角色管理不同仓库)。

4.2 Nexus 实战

4.2.1 Nexus 安装与启动(以 Nexus 2.12.0 为例)
  1. 安装准备

    • 解压 nexus-2.12.0-01-bundle.zip 到无中文路径的目录(如 D:\nexus);
    • 配置端口(可选):修改 conf/nexus.properties 中的 application-port(默认 8081,示例改为 8079):

    properties

    复制代码
    application-port=8079
    application-host=0.0.0.0
  2. 服务操作 (管理员身份运行 CMD):

    • 安装服务:cd D:\nexus\nexus-2.12.0-01\bin → 执行 nexus.bat install
    • 启动服务:nexus.bat start
    • 停止服务:nexus.bat stop
    • 卸载服务:nexus.bat uninstall
  3. 访问界面 :打开浏览器输入 http://localhost:8079/nexus,默认用户名 admin,密码 admin123

4.2.2 Nexus 仓库类型
仓库类型 作用 示例
Hosted(宿主仓库) 存储企业内部构件,分为:- Releases:稳定版本构件(如 1.0-RELEASE)- Snapshots:测试版本构件(如 0.0.1-SNAPSHOT)- 3rd party:第三方非中央仓库构件(如自研的特殊 JAR) 公司内部的 tx-utils-1.0-RELEASE.jar 存储到 Releases 仓库
Proxy(代理仓库) 代理远程公共仓库(如中央仓库),自动下载构件到本地,供内部项目使用 代理 Maven 中央仓库,项目请求 JUnit 时,Nexus 先从中央仓库下载到 Proxy 仓库,再提供给项目
Group(仓库组) 合并多个 Hosted/Proxy 仓库,提供统一访问地址,简化项目配置 创建 public 仓库组,包含 Releases、Snapshots、Proxy(中央仓库),项目仅需配置 public 地址即可访问所有仓库
Virtual(虚拟仓库) 兼容 Maven 1 版本构件,目前极少使用 -
4.2.3 将项目发布到私服
  1. 配置客户端权限 (修改 settings.xml):在 <servers> 标签内配置私服的账号密码(用于校验上传权限):

    xml

    复制代码
    <server>
        <id>releases</id> <!-- 与私服 Releases 仓库 ID 对应 -->
        <username>admin</username>
        <password>admin123</password>
    </server>
    <server>
        <id>snapshots</id> <!-- 与私服 Snapshots 仓库 ID 对应 -->
        <username>admin</username>
        <password>admin123</password>
    </server>
  2. 配置项目发布地址 (修改项目 pom.xml):通过 <distributionManagement> 指定私服的 Releases/Snapshots 仓库地址:

    xml

    复制代码
    <distributionManagement>
        <!-- 稳定版本发布到 Releases 仓库 -->
        <repository>
            <id>releases</id> <!-- 与 settings.xml 中 server 的 id 一致 -->
            <url>http://localhost:8079/nexus/content/repositories/releases/</url>
        </repository>
        <!-- 测试版本发布到 Snapshots 仓库 -->
        <snapshotRepository>
            <id>snapshots</id> <!-- 与 settings.xml 中 server 的 id 一致 -->
            <url>http://localhost:8079/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>
  3. 执行发布命令

    • 进入项目根目录,执行 mvn clean deploy
    • 若项目版本为 RELEASE,自动发布到 Releases 仓库;若为 SNAPSHOT,自动发布到 Snapshots 仓库。
4.2.4 从私服下载 JAR 包
方式 1:配置镜像(推荐,全局生效)

修改 settings.xml,将所有依赖请求转发到私服仓库组:

xml

复制代码
<mirrors>
    <mirror>
        <id>nexus-maven</id>
        <mirrorOf>*</mirrorOf> <!-- 拦截所有请求,转发到私服 -->
        <name>Nexus Maven</name>
        <url>http://localhost:8079/nexus/content/groups/public/</url> <!-- 私服仓库组地址 -->
    </mirror>
</mirrors>
方式 2:配置 Profile(全局 / 项目生效)
  1. 全局配置 (修改 settings.xml):

    xml

    复制代码
    <!-- 定义 Profile -->
    <profiles>
        <profile>
            <id>dev</id>
            <!-- 依赖仓库 -->
            <repositories>
                <repository>
                    <id>nexus</id>
                    <url>http://localhost:8079/nexus/content/groups/public/</url>
                    <releases><enabled>true</enabled></releases> <!-- 允许下载稳定版 -->
                    <snapshots><enabled>true</enabled></snapshots> <!-- 允许下载测试版 -->
                </repository>
            </repositories>
            <!-- 插件仓库(Maven 插件从私服下载) -->
            <pluginRepositories>
                <pluginRepository>
                    <id>public</id>
                    <url>http://localhost:8079/nexus/content/groups/public/</url>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
    <!-- 激活 Profile -->
    <activeProfiles>
        <activeProfile>dev</activeProfile>
    </activeProfiles>
  2. 项目配置 (修改项目 pom.xml):在 pom.xml 中添加上述 <repositories><pluginRepositories> 配置(仅当前项目生效,不推荐,易重复)。

4.2.5 第三方 JAR 包发布到私服(以 fastjson 为例)
步骤 1:配置私服 3rd party 仓库权限

修改 settings.xml,添加 3rd party 仓库的账号密码:

xml

复制代码
<server>
    <id>thirdparty</id> <!-- 与 3rd party 仓库 ID 对应 -->
    <username>admin</username>
    <password>admin123</password>
</server>
步骤 2:执行部署命令

在 CMD 中执行以下命令(需指定 JAR 包路径、坐标、私服 3rd party 仓库地址):

bash

复制代码
mvn deploy:deploy-file 
  -DgroupId=com.alibaba 
  -DartifactId=fastjson 
  -Dversion=1.1.37 
  -Dpackaging=jar 
  -Dfile=D:\fastjson-1.1.37.jar  <!-- 本地 JAR 包路径 -->
  -Durl=http://localhost:8079/nexus/content/repositories/thirdparty/  <!-- 3rd party 仓库地址 -->
  -DrepositoryId=thirdparty  <!-- 与 settings.xml 中 server 的 id 一致 -->
验证

登录 Nexus 界面,进入 3rd party 仓库,可看到 com/alibaba/fastjson/1.1.37 路径下的 JAR 包。

相关推荐
重整旗鼓~3 小时前
32.图片上传功能
java·redis
菜鸡儿齐3 小时前
ThreadLocal介绍
java·开发语言
lcu1113 小时前
Java 学习25:break 和 continue 语句
java
Icoolkj3 小时前
手机物理内存云共享—技术挑战与突破路径分析
java·服务器·智能手机
Hello.Reader3 小时前
Flink DataStream API 基础构件DataStream × Partitioning × ProcessFunction
java·大数据·flink
今日说"法"3 小时前
Rust 内存泄漏的检测与防范:超越安全的实践指南
java·安全·rust
欠你一个bug3 小时前
Java设计模式应用--装饰器模式
java·设计模式·装饰器模式
兔兔爱学习兔兔爱学习8 小时前
Spring Al学习7:ImageModel
java·学习·spring
lang201509289 小时前
Spring远程调用与Web服务全解析
java·前端·spring