Java 后端详解(六):Maven 与本地开发指南

上一篇:Java 后端详解(五):Redis 缓存


一、Maven 类似前端的什么?

Maven(mvn)在前端没有单一对应物,它同时承担「装依赖 + 定义构建流程 + 调用插件编译打包」几件事。可以把它理解成下面这一组工具的组合:

Maven 前端类似物 作用
mvn npm / yarn / pnpm 安装依赖、执行构建命令
pom.xml package.json 项目名、版本、依赖列表
mvn clean package npm run build 清理旧产物并打包
~/.m2/repository 全局 npm 缓存 下载的 jar 存放在本地仓库
<dependency> dependencies / devDependencies 声明第三方库
多模块(api + impl) monorepo(npm/pnpm workspaces) 一个仓库里多个子包
mvnw / mvnw.cmd Volta / Corepack / .nvmrc 锁定构建工具版本,团队一致
.mvn/settings.xml .npmrc 私有源、镜像、认证
Maven 插件 Vite / Webpack / esbuild 真正执行编译、打包(如 compilerspring-boot-maven-plugin

一句话记忆

Maven ≈ npm + 一套固定的构建流水线

前端 scripts 里自己写 devbuildtest;Maven 则用固定生命周期阶段:compiletestpackage

常用命令对照

目的 Maven 前端
安装依赖 mvn dependency:resolve(构建时自动) npm install
本地跑服务 mvn spring-boot:run npm run dev
打生产包 mvn package npm run build
发布到私服 mvn deploy npm publish
跑测试 mvn test npm test
清理 mvn clean rm -rf dist

二、为什么需要 mvnwmvnw.cmd

这两个文件是 Maven Wrapper 的启动脚本,功能相同,只是面向不同系统:

文件 适用环境
mvnw Linux / macOS / Git Bash
mvnw.cmd Windows(PowerShell / CMD)

解决的问题

  1. 不强制本机预装 Maven

    首次执行时会按 .mvn/wrapper/maven-wrapper.properties 自动下载 Maven 3.9.9

  2. 统一团队 Maven 版本

    避免「我这边 3.6 能编、你那边 3.9 报错」的环境差异。本项目 spring-boot-maven-plugin 对 Maven 版本较敏感,因此锁定 3.9.9。

  3. 自动加载项目配置

    .mvn/maven.config 会在每次构建时生效:

    ini 复制代码
    -s .mvn/settings.xml
    -Dmaven.wagon.http.allowInsecureProtocol=true

    等价于每次手动加:

    powershell 复制代码
    mvn -s .mvn/settings.xml -Dmaven.wagon.http.allowInsecureProtocol=true ...

    其中 settings.xml 配置了公司内网 Nexus;allowInsecureProtocol 允许访问 http:// 私服。详见 第三节

  4. 替代仓库内嵌完整 Maven

    以前可能在 .tools/apache-maven-3.9.6 放一整份 Maven;Wrapper 只提交小脚本,本体按需下载,是业界常见做法。

和直接 mvn 的关系

.\mvnw.cmd 系统 mvn
Maven 版本 固定 3.9.9 取决于本机安装
项目 settings 自动加载 需手动 -s
是否必须 推荐 可替代,但不保证版本一致

三、.mvn/settings.xml 详解

这是 Maven 的项目级配置文件 ,类似前端的 .npmrc :告诉 Maven 从哪下载 jar、如何访问公司私服(Nexus)。放在项目 .mvn/ 下而非用户目录 ~/.m2/settings.xml,clone 后团队构建行为一致。

通过 .mvn/maven.config 自动加载:

ini 复制代码
-s .mvn/settings.xml
-Dmaven.wagon.http.allowInsecureProtocol=true
参数 作用
-s .mvn/settings.xml 使用项目自带的 settings
-Dmaven.wagon.http.allowInsecureProtocol=true 允许访问 http:// 私服(Maven 3.8+ 默认拦截 HTTP)

3.1 <mirrors> --- HTTP 镜像

xml 复制代码
<mirror>
    <id>nexus-http</id>
    <mirrorOf>external:http:*</mirrorOf>
    <url>http://nexus.os.adc.com/nexus/content/groups/public/</url>
</mirror>
字段 含义
mirrorOf = external:http:* 所有外部 HTTP 仓库的请求,统一走这个镜像
url 公司内网 Nexus 的 public 组(聚合多个仓库)

Maven 3.8+ 默认禁止 HTTP 仓库。私服地址是 http://,因此需要 mirror + allowInsecureProtocol 配合使用。类比 npm:把 HTTP 源请求统一转发到公司私服

3.2 <profiles> --- 仓库列表

定义名为 nexus 的配置集,声明去哪拉依赖

依赖仓库 <repositories>

仓库 id URL 拉什么
central https://repo.maven.apache.org/maven2 开源正式版(如 Spring Boot)
nexus-releases http://nexus.os.adc.com/.../releases/ 公司内网正式发布的包
nexus-snapshots http://nexus.os.adc.com/.../snapshots/ 公司内网快照版

每个仓库用 <releases> / <snapshots> 控制只拉对应类型。本项目大量依赖 SNAPSHOT(如 crypto-base-function:1.0.6-SNAPSHOT),主要靠 nexus-snapshots

插件仓库 <pluginRepositories>

xml 复制代码
<pluginRepository>
    <id>central</id>
    <url>https://repo.maven.apache.org/maven2</url>
</pluginRepository>

Maven 构建插件compilerspring-boot-maven-plugin 等)的下载源,与项目依赖仓库分开配置。

3.3 <activeProfiles> --- 自动启用

xml 复制代码
<activeProfiles>
    <activeProfile>nexus</activeProfile>
</activeProfiles>

无需每次手动加 -Pnexus,构建时自动激活上面的 nexus profile。

3.4 构建时的解析流程

lua 复制代码
执行 .\mvnw.cmd clean package
        ↓
读取 maven.config → 加载 settings.xml + 允许 HTTP
        ↓
激活 nexus profile → 可用 central + nexus-releases + nexus-snapshots
        ↓
pom.xml 声明的依赖按类型去对应仓库解析
        ↓
下载到 ~/.m2/repository(本地缓存,类似 node 全局缓存)
        ↓
HTTP 请求经 mirror 走 nexus.os.adc.com

3.5 与 pom.xml 的分工

文件 方向 作用
.mvn/settings.xml pull(下载) 构建时从哪拉依赖和插件
pom.xmldistributionManagement push(发布) mvn deploy 时往哪推包

发布与多模块的完整说明见 第五节

3.6 前端类比小结

settings.xml 前端类似
repositories .npmrc 里多个 registry=
nexus-snapshots 私服上的 beta / nightly 通道
mirrors npm 镜像源
activeProfiles 默认生效的 registry 配置
allowInsecureProtocol 允许非 HTTPS 源(内网常见)

3.7 注意点

  1. 必须连内网 / VPN 才能访问 nexus.os.adc.com,否则 SNAPSHOT 依赖拉不下来。
  2. 当前文件不含 <servers> 账号密码,说明拉包走内网免密或匿名;不要把密码提交进仓库。
  3. IDE 若直接用系统 mvn 且未指定 -s .mvn/settings.xml,可能与命令行 mvnw 行为不一致;建议 IDE Maven 设置指向这份文件,或统一用 mvnw

四、本项目结构速览

bash 复制代码
crypto-auth-provider/
├── pom.xml                          # 根 POM(类似根 package.json + workspace 配置)
├── mvnw / mvnw.cmd                  # Maven Wrapper 入口
├── .mvn/
│   ├── maven.config                 # 默认 Maven 参数
│   ├── settings.xml                 # 私服 / Nexus 配置
│   └── wrapper/maven-wrapper.properties
├── crypto-auth-provider-api/        # API 契约模块(类似 shared types 包)
│   └── pom.xml
└── crypto-auth-provider-impl/       # 可运行服务(类似 apps/web)
    ├── pom.xml
    ├── conf/                        # 本地运行配置(gitignore,需自备)
    └── src/main/java/.../Application.java

pom.xml 里常见概念

Maven 前端类比
<groupId> + <artifactId> @scope/package-name
<version>${revision}</version> version 字段
<modules> workspaces 子包列表
<dependencyManagement> 统一锁版本(类似 resolutions / overrides)
<dependencies> dependencies

五、多模块与发布(deploy)

日常 mvn clean package 不会上传 任何东西到 Nexus;只有 mvn deploy 才会把产物推到私服。本节说明根 pom.xml<modules><distributionManagement> 与各子模块 deploy.skip 如何配合。

5.1 <modules> 是干什么的?

xml 复制代码
<modules>
    <module>crypto-auth-provider-api</module>
    <module>crypto-auth-provider-impl</module>
</modules>

这是 多模块聚合(reactor) 声明:在根目录执行 Maven 时,会按顺序构建这两个子项目。类比前端 monorepo 的 workspaces

作用 说明
mvn clean package 两个模块都会编译打包
mvn deploy 遍历两个模块,但每个模块是否实际上传另说
构建顺序 先 api,再 impl(impl 依赖 api)

<modules> 不是「勾选要上传哪个包」 ,只定义「工程里有哪些子项目、构建时一起跑」。指定单个模块用 -pl,例如 mvn deploy -pl crypto-auth-provider-api

5.2 <distributionManagement> --- 上传目标

xml 复制代码
<distributionManagement>
    <repository>
        <id>nexus-releases</id>
        <name>Nexus Release Repository</name>
        <url>http://nexus.os.adc.com/nexus/content/repositories/releases/</url>
    </repository>
    <snapshotRepository>
        <id>nexus-snapshots</id>
        <url>http://nexus.os.adc.com/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
</distributionManagement>
节点 何时使用 地址
<repository> 版本不以 -SNAPSHOT 结尾 .../repositories/releases/
<snapshotRepository> 版本以 -SNAPSHOT 结尾 .../repositories/snapshots/

当前版本 ${revision} = 2026.07.01(无 -SNAPSHOT)→ 若 deploy,进 releases 。若改成 2026.07.01-SNAPSHOT,则进 snapshots(同坐标可反复覆盖上传)。

<id> 需与 .mvn/settings.xml 中仓库 id 一致;若 deploy 要账号,在 settings 的 <servers> 里按 id 配置(当前项目 settings 未配 servers,日常多为本机只拉包、由 CI 发布)。

5.3 mvn deploy 流程

在根目录执行 mvn deploy 时:

go 复制代码
mvn deploy(crypto-auth-provider 根目录)
        │
        ▼
读取 <modules>,建立 reactor 构建顺序
        │
        ├── 1. 根 crypto-auth-provider(packaging=pom)
        │       → 可上传父 POM 元数据
        │
        ├── 2. crypto-auth-provider-api(jar)
        │       → compile → package → 上传到 Nexus
        │
        └── 3. crypto-auth-provider-impl(jar)
                → compile → package → 是否上传?看 deploy.skip
        │
        ▼
按 <version> 选择 releases 或 snapshots 仓库
        │
        ▼
上传 jar、pom、sources.jar 等(若该模块未 skip deploy)

每个会 deploy 的模块通常上传:

文件 作用
xxx.jar 代码包
xxx.pom 坐标与依赖声明
xxx-sources.jar 源码包(若配置了 source 插件)

5.4 本项目:谁会上传、谁不会?

crypto-auth-provider-impl/pom.xml 中:

xml 复制代码
<maven.deploy.skip>true</maven.deploy.skip>

表示 impl 不参与 deploy ,即使它在 <modules> 里、会参与 package

模块 packaging deploy 实际上传?
crypto-auth-provider pom 默认 父 POM 元数据
crypto-auth-provider-api jar 未 skip 会上传 ,供其他服务 dependency 引用
crypto-auth-provider-impl jar deploy.skip=true 不上传(可运行服务,打 tar.gz 给运维部署)

常见分工:

  • api :对外契约(AuthFacade、DTO)→ 需要 npm publish 式的发布
  • impl :Spring Boot 可执行服务 → 只 package 部署,不进 Maven 私服

典型 deploy 结果:api 的 jar 进 Nexus ,impl 仅本地 target/ 产物。

5.5 命令与场景对照

命令 是否上传 Nexus 说明
mvn clean package 只打本地 target/
mvn install 只装到本机 ~/.m2
mvn deploy 按各模块 skip 规则上传
mvn deploy -pl crypto-auth-provider-api 是(仅 api) 只发布指定模块

发布通常需要:内网可达 Nexus、deploy 权限、settings 中 <servers> 认证(若私服要求)。

5.6 三块配置如何串联

xml 复制代码
┌─────────────────────────────────────────────────────────┐
│  pom.xml <modules>                                       │
│  → 有哪些子项目、构建顺序                                 │
└────────────────────┬────────────────────────────────────┘
                     ▼
┌─────────────────────────────────────────────────────────┐
│  各子模块:packaging、maven.deploy.skip                   │
│  → 该模块要不要 deploy、产物类型                           │
└────────────────────┬────────────────────────────────────┘
                     ▼
┌─────────────────────────────────────────────────────────┐
│  根 pom <distributionManagement>                         │
│  → 上传到 Nexus releases / snapshots                     │
└────────────────────┬────────────────────────────────────┘
                     ▼
┌─────────────────────────────────────────────────────────┐
│  settings.xml <servers>(若配置)                         │
│  → deploy 认证                                           │
└─────────────────────────────────────────────────────────┘

5.7 前端类比

Maven 前端
<modules> monorepo workspaces 列表
mvn deploy npm publish
maven.deploy.skip 子包 "private": true 或不参与 publish
distributionManagement publish 目标 registry
api 模块 可发布的 @scope/crypto-auth-provider-api
impl 模块 只部署的服务端应用,不 publish 成 npm 包

六、构建命令

在项目根目录执行(Windows PowerShell 注意给 -D 参数加引号):

powershell 复制代码
cd F:\java\crypto-auth-provider
.\mvnw.cmd clean package "-Dmaven.test.skip=true"

成功后会生成:

  • crypto-auth-provider-impl/target/crypto-auth-provider.jar --- 可执行 jar
  • crypto-auth-provider-impl/target/crypto-auth-provider-bin.tar.gz --- 部署包(含 bin、lib)

常见坑

现象 原因 处理
Unknown lifecycle phase ".test.skip=true" PowerShell 把 -D 拆开了 写成 "-Dmaven.test.skip=true"
父 POM / 依赖找不到 未连内网或 Nexus 不可达 连 VPN,确认 .mvn/settings.xml
spring-boot-maven-plugin 报错 Maven 版本或插件依赖问题 使用 mvnw,不要混用过旧 Maven

七、package 不会启动服务

重要:mvn clean package 只编译打包,不会启动 Spring Boot 进程。

如果执行 package 后访问 http://localhost:8080/health 仍有响应,通常是:

  1. 本机已有旧进程在跑 (例如 IDE 之前启动的 Application
  2. 8080 被其他项目占用 (需用 netstat 确认 PID 和主类)

验证方式:

powershell 复制代码
netstat -ano | findstr "LISTENING" | findstr "808"

确认监听 8080 的进程是否真的是 com.allawn.crypto.provider.Application


八、本地启动

前置条件

  • JDK 11+
  • 公司内网 / VPN(Heracles、Euler 注册中心、Nexus)
  • crypto-auth-provider-impl/conf/ 目录存在(本地配置,通常不进 git)

方式一:IDE(推荐调试)

  1. 主类:com.allawn.crypto.provider.Application

  2. Working directory:crypto-auth-provider-impl

  3. VM options 建议:

    ini 复制代码
    -Dloader.path=conf
    -Dheracles.bootstrap.enabled=true
    -Ddubbo.consumer.check=false

    dubbo.consumer.check=false 表示下游 crypto-key-dist-provider 不在线时也能先启动(真正调签名接口时仍会依赖它)。

方式二:Maven 启动

powershell 复制代码
.\mvnw.cmd -pl crypto-auth-provider-impl spring-boot:run "-Dmaven.test.skip=true" "-Dspring-boot.run.jvmArguments=-Dloader.path=conf -Ddubbo.consumer.check=false"

方式三:jar 启动

powershell 复制代码
cd crypto-auth-provider-impl
java -Dloader.path=conf -Dheracles.bootstrap.enabled=true -jar target\crypto-auth-provider.jar

验证

powershell 复制代码
curl http://localhost:8080/health
# 期望返回:OK

签名接口示例见 crypto-auth-provider-impl/http/sign.http

端口说明

服务 默认端口
HTTP 8080application.propertiesserver.port
Dubbo 20880
Dubbo QoS 诊断 22222http://localhost:22222/ls

九、速查卡片

powershell 复制代码
# 构建
.\mvnw.cmd clean package "-Dmaven.test.skip=true"

# 发布到 Nexus(通常仅 api 模块;impl 已 deploy.skip)
.\mvnw.cmd deploy -pl crypto-auth-provider-api

# 启动(Maven)
.\mvnw.cmd -pl crypto-auth-provider-impl spring-boot:run "-Dmaven.test.skip=true" "-Dspring-boot.run.jvmArguments=-Dloader.path=conf -Ddubbo.consumer.check=false"

# 健康检查
curl http://localhost:8080/health

# 看谁占了端口
netstat -ano | findstr ":8080"
相关推荐
触底反弹1 小时前
🎲 纯 CSS 搞定 3D 旋转立方体?还附赠一个「天坑」解决方案!
前端·css·html
盗德1 小时前
LangChain.js 中文开发手册(记录)
前端
tonydf1 小时前
.NET 项目集成可观测性:从架构思考到落地实践
运维·后端
梨子同志1 小时前
PostgreSQL
后端
Geek-Chow2 小时前
微服务认证与授权:01 — 概念
java·前端·数据库
AskHarries2 小时前
用 OpenClaw 做视频脚本:选题、分镜、旁白和镜头表
后端·程序员
狂炫冰美式2 小时前
凌晨睡不着,我给台风巴威写了个追踪网站
前端·后端·github
程序员cxuan3 小时前
Claude Code 焚诀(一):Claude Code 六种心智模型
人工智能·后端
雪隐3 小时前
用Flutter做背单词APP-01服务器?不存在的,我家里就有
前端·人工智能·后端