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

    • 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章 多模块项目深入

    • Reactor构建顺序
    • 继承与聚合组合实践
    • 模块间依赖
  • 第2章 插件体系深入

    • 插件目标goal
    • execution与自定义绑定
    • pluginManagement
  • 第3章 Profile高级应用

    • Profile激活机制
    • Profile与Spring Profile区别
  • 第4章 部署与分发

    • distributionManagement
    • mvn deploy
    • settings.xml认证配置
  • 第5章 CI/CD集成

    • Maven与持续集成
  • 第6章 自定义插件开发

    • 自定义插件开发
  • 第7章 高级依赖管理

    • 快照版本机制
    • 依赖分析工具
  • 第8章 仓库管理深入

    • 仓库组与路由

distributionManagement

本章是"部署与分发"主题的起点。入门教程讲解了本地仓库和私服的概念,本章解决"如何把构建产物从本地推送到远程仓库"的具体配置问题。理解distributionManagement,是团队协作中共享构件的前提。


核心机制

distributionManagement是pom.xml中专门定义远程部署目标的标签。它告诉Maven:执行mvn deploy时,应该把jar包、pom文件和附属构件(如源码包、文档包)上传到哪个远程仓库。

入门教程已经讲过,Maven的仓库体系分为本地仓库(~/.m2/repository)和远程仓库(中央仓库、私服等)。mvn install把构件放进本地仓库,仅供本机使用;mvn deploy把构件推送到远程仓库,供整个团队甚至外部用户下载。而distributionManagement就是deploy命令的"导航地图"。

distributionManagement的结构

<distributionManagement>
    <!-- 发布版仓库:version不含SNAPSHOT时部署到这里 -->
    <repository>
        <id>feixiang-releases</id>
        <name>飞翔科技发布仓库</name>
        <url>http://nexus.feixiang.com/repository/maven-releases/</url>
    </repository>

    <!-- 快照版仓库:version含SNAPSHOT时部署到这里 -->
    <snapshotRepository>
        <id>feixiang-snapshots</id>
        <name>飞翔科技快照仓库</name>
        <url>http://nexus.feixiang.com/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>

三个关键设计决策

  1. 为什么要分开repository和snapshotRepository? 发布版(Release)和快照版(Snapshot)的治理策略完全不同。Release一旦上传不可覆盖,保证可复现性;Snapshot允许反复覆盖,支持持续集成。物理隔离到不同仓库,是Nexus/Artifactory等私服的标准实践。

  2. id的作用是什么?id不是URL的别名,而是认证凭证的绑定键。settings.xml中<server>标签的id必须与这里完全匹配,Maven才能找到对应的用户名密码。同一个URL可以配多个id,对应不同的权限账号。

  3. url支持哪些协议? Maven 3.x支持http://、https://、scp://、sftp://和file://。其中http/https最常见,对应Nexus或Artifactory;scp/sftp用于直接推送到远程服务器目录;file://用于本地文件系统测试(如共享目录模拟仓库)。

生活类比:快递发货系统

想象飞翔科技的电商仓库:

  • 本地仓库(mvn install):公司楼下的自提柜。你自己把包裹放进去,只有你自己能取。
  • 远程仓库(mvn deploy):全国分拨中心。你把包裹交给快递员(deploy插件),由分拨中心统一管理和分发。
  • distributionManagement:你贴在包裹上的发货单,写明"发往华东分拨中心"还是"华南分拨中心"。
  • repository vs snapshotRepository:普通商品走"标准物流"(Release仓库),生鲜冷链走"特快专递"(Snapshot仓库)——不同的通道、不同的处理规则。

图示

上图展示了deploy的完整链路。distributionManagement是决策分叉点:根据version是否包含SNAPSHOT,选择不同的目标仓库。无论走哪条路,都必须经过settings.xml的认证检查——没有匹配的server配置,上传会被拒绝。


完整示例

场景

飞翔科技的order-service项目开发到1.2.0版本,需要部署到公司私服。CTO大翔的要求是:

  1. SNAPSHOT版本自动进快照库,方便前端黄俪随时联调最新后端
  2. RELEASE版本进发布库,只有架构师白歌审批后才能正式发布
  3. 源码包和文档包必须一起部署,方便其他团队调试

完整pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.feixiang</groupId>
    <artifactId>order-service</artifactId>
    <version>1.2.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>飞翔科技订单服务</name>
    <description>订单核心服务,供商城、支付、物流模块调用</description>

    <!-- 部署目标配置 -->
    <distributionManagement>
        <repository>
            <id>feixiang-releases</id>
            <name>飞翔科技Maven发布仓库</name>
            <url>https://nexus.feixiang.com/repository/maven-releases/</url>
        </repository>
        <snapshotRepository>
            <id>feixiang-snapshots</id>
            <name>飞翔科技Maven快照仓库</name>
            <url>https://nexus.feixiang.com/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <build>
        <plugins>
            <!-- 源码插件:打包时生成-sources.jar -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!-- 文档插件:打包时生成-javadoc.jar -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>3.4.1</version>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

各角色的部署操作

小崔(后端开发)的日常快照部署:

# 小崔完成一个功能后,部署快照版供黄俪联调
mvn clean deploy
# 效果:1.2.0-SNAPSHOT上传到feixiang-snapshots仓库
# 黄俪的pom.xml里写<version>1.2.0-SNAPSHOT</version>,Maven自动下载最新快照

白歌(架构师)的正式发布:

# 1. 先修改pom.xml版本号:1.2.0-SNAPSHOT -> 1.2.0
mvn versions:set -DnewVersion=1.2.0

# 2. 部署到发布仓库(此时version不含SNAPSHOT,走repository路径)
mvn clean deploy
# 效果:1.2.0上传到feixiang-releases仓库,不可覆盖

李眉(运维)的私服检查:

# 李眉在Nexus管理界面确认构件已到位
# 访问 https://nexus.feixiang.com/
# 在maven-snapshots仓库看到:com/feixiang/order-service/1.2.0-SNAPSHOT/
# 在maven-releases仓库看到:com/feixiang/order-service/1.2.0/

易错点与常见问题

误区一:只配repository,不配snapshotRepository

错误认知:"我们公司只有一个仓库,Release和Snapshot都往里面放,所以只写repository就够了。"

纠正:Maven 3.x的deploy插件会严格区分version类型。如果你的version是1.0-SNAPSHOT但pom.xml里只有<repository>没有<snapshotRepository>,deploy会失败:

Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.8.2:deploy
Deployment failed: repository element was not specified in the POM
inside distributionManagement element

错误信息具有误导性——它说"repository element was not specified",实际上你的repository是配了的,只是Maven要求SNAPSHOT必须走snapshotRepository。正确做法是两者都配,即使指向同一个URL:

<distributionManagement>
    <repository>
        <id>feixiang</id>
        <url>https://nexus.feixiang.com/repository/maven-public/</url>
    </repository>
    <snapshotRepository>
        <id>feixiang</id>
        <url>https://nexus.feixiang.com/repository/maven-public/</url>
    </snapshotRepository>
</distributionManagement>

误区二:id随便写,与settings.xml不对应

错误认知:"id就是个名字,我写nexus或my-repo都行,反正URL对了就能传上去。"

纠正:id是认证绑定的唯一标识。deploy插件上传时,会用distributionManagement里的id去settings.xml里找同名的<server>标签。如果id不匹配,即使URL正确、账号密码在settings.xml里存在,Maven也会匿名上传,被私服拒绝:

Return code is: 401, ReasonPhrase: Unauthorized

反例:

<!-- pom.xml -->
<repository>
    <id>feixiang-releases</id>
    <url>https://nexus.feixiang.com/...</url>
</repository>

<!-- settings.xml -->
<server>
    <id>feixiang-release</id>  <!-- 注意:releases vs release,少了个s -->
    <username>deployer</username>
    <password>xxx</password>
</server>

id差一个字符,认证就会失败。建议建立团队规范:id命名统一、大小写敏感、定期核对。

误区三:http协议未配置镜像时直接使用

错误认知:"我们公司内网Nexus用http,不需要证书,直接写URL就行。"

纠正:Maven 3.8.1+默认阻止http协议的仓库(中央仓库强制https)。如果你的私服还在用http,需要在settings.xml中配置镜像例外,或者在命令行添加参数:

# Maven 3.8.1+ 临时允许http(不推荐用于生产)
mvn clean deploy -Dmaven.wagon.http.ssl.insecure=true

正确做法:将私服升级为https,或在settings.xml中配置允许http的镜像:

<mirror>
    <id>feixiang-http-allow</id>
    <mirrorOf>feixiang-releases,feixiang-snapshots</mirrorOf>
    <url>http://nexus.feixiang.com/...</url>
    <blocked>false</blocked>
</mirror>

小结

distributionManagement是Maven部署体系的"导航地图",它通过repository和snapshotRepository两个标签,精确控制Release和Snapshot构件的上传目的地。配置时需注意三点:

  1. 两者缺一不可,SNAPSHOT版本必须有snapshotRepository
  2. id必须与settings.xml中的server对应,否则认证失败
  3. 协议选择要符合Maven版本要求,3.8.1+默认禁用http

配合maven-source-plugin和maven-javadoc-plugin,可以确保源码和文档随主构件一起部署,提升团队协作效率。

本章与全局的关系:本章解决了"往哪部署"的配置问题。下一章将讲解mvn deploy命令本身——deploy生命周期阶段、与install的区别、以及SNAPSHOT的特殊部署行为。

下一页
mvn deploy