乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 介绍与核心概念

    • Maven是什么
    • 约定优于配置
  • 第2章 安装与配置

    • 安装与验证
    • settings.xml
    • 本地仓库与镜像
  • 第3章 POM与项目坐标

    • POM
    • GAV坐标
    • packaging
  • 第4章 标准目录布局

    • 标准目录布局
  • 第5章 依赖机制

    • dependencies
    • scope
    • 依赖传递
    • 依赖冲突与调解
    • exclusions
    • optional
    • dependencyManagement
  • 第6章 仓库

    • 仓库体系
    • 本地仓库
    • 远程仓库与镜像
    • 私服
  • 第7章 构建生命周期

    • 生命周期概述
    • clean 生命周期
    • default 生命周期
    • site 生命周期
    • 生命周期与插件绑定
  • 第8章 插件

    • 插件概述
    • maven-compiler-plugin
    • maven-surefire-plugin
    • maven-war-plugin
  • 第9章 继承与聚合

    • parent继承
    • 聚合
    • BOM
    • properties
  • 第10章 属性与资源过滤

    • 资源过滤
    • Profile
  • 第11章 常用命令

    • mvn compile
    • mvn test
    • mvn package
    • mvn clean
    • mvn install
    • mvn dependency:tree
  • 第12章 常见问题与最佳实践

    • 依赖冲突排查
    • 最佳实践

GAV坐标

本章承接"POM",深入讲解 Maven 的寻址系统。如果说 POM 是项目的"DNA",那么 GAV 坐标就是项目的"身份证号"——它让 Maven 能在本地仓库、远程仓库、中央仓库的亿万 JAR 中,唯一、精确、无歧义地找到你需要的那个依赖。


核心机制

POM 为项目定义了以下坐标——groupId、artifactId、version 和 packaging。其中 groupId:artifactId:version 三者组合,构成了 Maven 世界里的唯一标识符。

Maven 使用 coordinates(坐标)这个词,而不是 "ID" 或 "name"。这个词的选择非常精准:

  • 在数学中,坐标(如 x, y, z)能在三维空间中唯一确定一个点
  • 在 Maven 中,GAV(groupId:artifactId:version)能在仓库的无限空间中唯一确定一个项目

没有坐标系统,Maven 的依赖管理、传递依赖、版本解析都将无从谈起。

三要素各司其职

元素含义命名规范示例
groupId组织或团体的唯一标识公司域名的倒写com.feixiang
artifactId项目或模块的名称简短、无空格、全小写employee-system
version当前构建的版本号三段式语义化版本1.0.0-SNAPSHOT

三者组合成完整坐标:com.feixiang:employee-system:1.0.0-SNAPSHOT

groupId:"你来自哪个组织"

groupId 回答的问题是:"这个项目是谁生的?"它通常采用公司域名的倒写,这是 Java 世界沿袭多年的包命名惯例。

  • 飞翔科技的官网是 www.feixiang.com,所以 groupId 是 com.feixiang
  • 如果飞翔科技有一个内部平台事业部,可以进一步细分为 com.feixiang.platform
  • 如果是一个开源项目没有域名,可以用 GitHub 地址,如 io.github.feixiangtech

artifactId:"你叫什么名字"

artifactId 回答的问题是:"这个项目本身叫什么?"它是坐标中最具辨识度的部分。

  • 员工管理系统 → employee-system
  • 薪资计算服务 → payroll-service
  • 公共工具包 → feixiang-common

命名建议:

  • 全小写,用连字符 - 分隔单词(不要用下划线 _ 或驼峰)
  • 不要包含 groupId 的信息(不要叫 com-feixiang-employee-system)
  • 多模块项目中,子模块的 artifactId 应该体现模块职责,如 employee-system-web、employee-system-service

version:"你是第几代"

version 回答的问题是:"这是哪个版本的构建?"Maven 采用**语义化版本控制(SemVer)**的惯例:

主版本号.次版本号.修订号[-标签]
  • 主版本号(Major):不兼容的 API 修改,如 1.x.x → 2.0.0
  • 次版本号(Minor):向下兼容的功能新增,如 1.0.x → 1.1.0
  • 修订号(Patch):向下兼容的问题修复,如 1.0.0 → 1.0.1
  • 标签(Label):特殊版本标识,如 -SNAPSHOT(开发中快照)、-RC1(候选发布版)

SNAPSHOT 是 Maven 的特殊概念,表示"这个版本还在开发中,每天可能变"。Maven 遇到 SNAPSHOT 版本时,会每天检查远程仓库是否有更新,而正式版本(如 1.0.0)一旦下载到本地,永远不会再去远程检查。

生活类比:图书馆索书号

想象 Maven 仓库是一座巨型图书馆,里面存放着全世界所有 Java 项目的 JAR 包。GAV 坐标就是每本书的索书号。

  • groupId = 出版社 + 分类号。例如"清华大学出版社 / 计算机科学类",告诉你这本书来自哪个机构、属于哪个领域。
  • artifactId = 书名。例如"深入理解 Java 虚拟机",告诉你这本书本身叫什么。
  • version = 版次。例如"第 3 版",告诉你这是哪个印刷批次的内容。

当你(开发者)想借一本书(引入一个依赖),你只需要在借书单(pom.xml)上填写索书号(GAV)。图书馆管理员(Maven 引擎)根据索书号,先到你的私人书架(本地仓库)找,找不到就去社区分馆(镜像)或总馆(中央仓库)调阅,最终把书送到你手上。

没有索书号,图书馆就是一堆混乱的纸堆;没有 GAV,仓库就是一堆无名的 JAR 包。


图示

上图展示了 GAV 坐标与仓库物理路径的映射关系:groupId 的每个点号分隔段变成一级目录,artifactId 再变一级,version 再变一级,最终 JAR 文件落在最深层。这种层级结构让文件系统能高效存储和检索海量依赖。


完整示例

场景

飞翔科技有三个项目同时开发:

  1. employee-system:员工管理系统(Web 应用)
  2. payroll-service:薪资计算服务(后端服务)
  3. feixiang-common:公共工具包(被前两个项目共用)

CTO 大翔要求所有项目的坐标必须规范,方便后续依赖管理和版本追溯。架构师白歌负责制定坐标规范,小崔负责在 pom.xml 中落实。

操作前:坐标混乱的隐患

假设没有规范,三个项目的坐标可能写成:

项目错误 groupId错误 artifactId问题
员工系统feixiangEmployeeSystem域名未倒写;驼峰命名不规范
薪资服务com.feixiang.techpayroll过度细分 groupId;artifactId 语义不清
公共包com.FeiXiangcommon-utils大小写混乱;artifactId 过于通用

这种混乱会导致:

  • 小崔在 employee-system 里声明依赖时,不确定该写 feixiang:EmployeeSystem 还是 com.feixiang:employee-system
  • 黄俪的前端项目(Node.js 构建)调用 Maven 仓库 API 时,大小写敏感导致 404
  • 李眉排查生产问题时,从 JAR 包反推坐标,发现 common-utils 这个 artifactId 根本不知道是哪个团队的

操作步骤

步骤 1:白歌制定坐标规范

白歌在团队 Wiki 上发布《飞翔科技 Maven 坐标规范》:

groupId:    com.feixiang              # 全公司统一
            com.feixiang.platform      # 平台事业部(如需细分)

artifactId: {系统名}-{模块职责}         # 全小写,连字符分隔
            示例:employee-system、payroll-service、feixiang-common

version:    主.次.修-SNAPSHOT          # 开发阶段用 SNAPSHOT
            主.次.修                    # 正式发布去掉 SNAPSHOT

步骤 2:小崔配置三个项目的坐标

项目 1:employee-system

<project ...>
    <groupId>com.feixiang</groupId>
    <artifactId>employee-system</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>
</project>

项目 2:payroll-service

<project ...>
    <groupId>com.feixiang</groupId>
    <artifactId>payroll-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
</project>

项目 3:feixiang-common

<project ...>
    <groupId>com.feixiang</groupId>
    <artifactId>feixiang-common</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
</project>

步骤 3:小崔在 employee-system 中引用公共包

employee-system 需要用到 feixiang-common 里的工具类。小崔在 employee-system/pom.xml 中声明依赖:

<dependencies>
    <dependency>
        <groupId>com.feixiang</groupId>
        <artifactId>feixiang-common</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
</dependencies>

步骤 4:查看仓库中的物理路径

执行 mvn install 后,小崔查看本地仓库,验证坐标与路径的映射:

D:/maven-repo/
└── com/
    └── feixiang/
        ├── employee-system/
        │   └── 1.0.0-SNAPSHOT/
        │       ├── employee-system-1.0.0-SNAPSHOT.war
        │       └── employee-system-1.0.0-SNAPSHOT.pom
        ├── payroll-service/
        │   └── 1.0.0-SNAPSHOT/
        │       ├── payroll-service-1.0.0-SNAPSHOT.jar
        │       └── payroll-service-1.0.0-SNAPSHOT.pom
        └── feixiang-common/
            └── 1.0.0-SNAPSHOT/
                ├── feixiang-common-1.0.0-SNAPSHOT.jar
                ├── feixiang-common-1.0.0-SNAPSHOT.pom
                └── feixiang-common-1.0.0-SNAPSHOT-sources.jar

操作结果及分析

坐标元素在路径中的体现作用
com.feixiangcom/feixiang/ 两级目录隔离不同组织的项目
employee-systememployee-system/ 一级目录隔离同一组织下的不同项目
1.0.0-SNAPSHOT1.0.0-SNAPSHOT/ 一级目录隔离同一项目的不同版本

这种层级映射的精妙之处在于:坐标本身就是路径。Maven 不需要维护一个"坐标 → 路径"的索引表,它直接把坐标翻译成目录结构,O(1) 时间就能定位文件。


易错点与常见问题

误区一:groupId 不用域名倒写,用公司简称

错误配置:

<groupId>feixiang</groupId>   <!-- ❌ 没有 com 前缀,容易与其他组织冲突 -->

后果:

  • 如果另一家也叫"乐途"的公司(如北京飞翔科技、上海乐途网络)也用了 feixiang,仓库中就会发生冲突
  • 发布到 Maven 中央仓库时,会被拒绝——中央仓库要求 groupId 必须对应你拥有的域名

纠正:始终使用域名倒写,确保全球唯一性:

<groupId>com.feixiang</groupId>   <!-- ✅ 对应 feixiang.com -->

误区二:version 用日期格式

错误配置:

<version>20240115</version>   <!-- ❌ 不是语义化版本 -->

后果:

  • Maven 的版本解析算法(如"最近版本优先")对日期格式支持不佳
  • 团队成员无法从版本号判断这是修复版、功能版还是大改版
  • 与 Spring Boot、Spring Cloud 等生态的版本命名惯例不一致

纠正:使用三段式语义化版本:

<version>1.0.0</version>           <!-- 正式发布 -->
<version>1.1.0-SNAPSHOT</version>  <!-- 开发中,1.1 功能分支 -->
<version>1.0.1</version>           <!-- 1.0 线的修复版 -->

误区三:SNAPSHOT 版本发布到生产环境

错误做法:李眉在部署生产环境时,直接引用了 1.0.0-SNAPSHOT。

后果:

  • 今天构建时,1.0.0-SNAPSHOT 对应的是 A 版本的代码
  • 明天构建时,小崔提交了新代码,远程仓库的 1.0.0-SNAPSHOT 已经变成了 B 版本
  • 李眉重新部署,发现行为变了,但版本号还是 1.0.0-SNAPSHOT,无法追溯

纠正:

  • 开发阶段:使用 SNAPSHOT,方便团队共享最新进展
  • 发布阶段:执行 mvn versions:set -DnewVersion=1.0.0,去掉 SNAPSHOT,发布为正式版本
  • 生产环境:只依赖正式版本,确保构建可复现

小结

GAV 坐标(groupId:artifactId:version)是 Maven 仓库体系的寻址基石。groupId 标识组织(域名倒写),artifactId 标识项目(全小写连字符),version 标识版本(三段式语义化)。坐标不仅用于声明依赖,还直接映射为本地仓库的物理目录结构,是 Maven 高效检索依赖的根本机制。

本章与全局的关系:本章揭示了 Maven 如何通过"坐标"在仓库中唯一锁定一个项目。下一章"packaging"将讲解坐标的第四个要素——packaging,它决定了一个项目的"物理形态"是 JAR、WAR 还是 POM,直接影响构建产物和适用场景。

上一页
POM
下一页
packaging