前端转 Java,第一篇看懂 pom.xml:Maven 依赖管理从入门到不懵

如果你熟悉 package.json,那 pom.xml 其实就是一个"重度加强版"的 package.json


为什么是 pom.xml

前端项目中,package.json 定义了项目名、版本、依赖、脚本。Java 世界中(Maven 体系),这个文件就是 pom.xml

POM = Project Object Model,项目对象模型。它不只是依赖清单,它还描述了:

  • 项目叫什么、谁在维护、什么版本
  • 这个项目依赖哪些 jar 包
  • 这个项目怎么编译、怎么打包、怎么测试
  • 这个项目怎么发布到仓库

一个典型的 pom.xml 长这样:

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.yourcompany</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <!-- 依赖、构建、插件 ... -->
</project>

下面逐个拆解。


1. 项目坐标:groupId + artifactId + version

对应 package.json 里的 name + version,但分成了三段:

字段 含义 类比 示例
groupId 组织/公司标识,一般是域名反写 类似 npm scope @company/ com.yourcompany
artifactId 项目名称 类似 name my-app
version 版本号 完全等同 version 1.0.0-SNAPSHOT

三个合在一起,就是 Maven 世界里的 唯一坐标。任何 jar 包都靠这三个字段定位。

SNAPSHOT 是什么?

  • -SNAPSHOT = 快照版本,相当于前端 "开发中、还没发正式版"

  • Maven 每次构建时会检查远程仓库,看是否有更新的 SNAPSHOT

  • 去掉 -SNAPSHOT 就是正式版本,发布后不可修改

    1.0.0-SNAPSHOT → 开发中,可以随时覆盖
    1.0.0 → 正式版本,一旦发布就不能改

packaging:打包方式

含义 类比
jar 打成 jar 包(默认) 类似 npm 发布后的包
war 打成 war 包,部署到 Tomcat 等容器 类似打包后部署到 Nginx
pom 不打包,仅作为父 POM 管理子模块 类似 monorepo 的根 package.json

2. 依赖管理:dependencies

对应 package.jsondependencies + devDependencies

xml 复制代码
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.7.18</version>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>

    <!-- 测试依赖,只在测试阶段生效,类似 devDependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.7.18</version>
        <scope>test</scope>
    </dependency>
</dependencies>

2.1 scope:依赖范围(前端同学最需要理解的)

scope 决定了这个依赖在什么时候、在哪里可用。

scope 编译 测试 运行 打包 类比前端
compile(默认) dependencies
provided TypeScript 类型声明(编译时需要,运行时不需要)
runtime 只在运行时才需要的 polyfill
test devDependencies
system 不推荐,类似直接引用本地路径

典型例子

xml 复制代码
<!-- Servlet API,Tomcat 已经提供了,打包时不需要 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

<!-- Lombok,只在编译期生成代码,运行时不需要 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

2.2 传递依赖:Maven 的"依赖的依赖"

前端中,npm install react 会自动安装 react-domscheduler 等子依赖。Maven 也一样:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

这一个依赖会自动引入:spring-webmvcspring-webtomcat-embed-corejackson-databind ...... 几十个包。这就是 传递依赖(transitive dependency)。

查看传递依赖

bash 复制代码
mvn dependency:tree

输出类似:

csharp 复制代码
[INFO] com.yourcompany:my-app:jar:1.0.0-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.7.18:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.7.18:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.18:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.7.18:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.5:compile
[INFO] |  |  \- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.5:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.18:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.71:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.71:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.27:compile

2.3 排除某个传递依赖

类似 npm 中的 overrides,你可以排除某个不想要的传递依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- 不用 Tomcat,换成 Undertow -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

3. 统一版本管理:dependencyManagement

对应前端的 "版本锁定"(package-lock.json 的作用类似,但这里是主动声明)。

在多模块项目中,你希望所有子模块用同一个版本的 Spring、同一个版本的 MySQL 驱动,怎么办?父 POM 里用 <dependencyManagement> 统一声明版本。

xml 复制代码
<!-- 父 pom.xml -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>  <!-- 统一版本 -->
        </dependency>
    </dependencies>
</dependencyManagement>

子模块引用时不需要写版本号

xml 复制代码
<!-- 子模块 pom.xml -->
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <!-- 版本号从父 POM 继承,不用写 -->
    </dependency>
</dependencies>

Spring Boot 的 spring-boot-dependencies 就是这么做的

xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.18</version>
</parent>

引入这个 parent 之后,你加 spring-boot-starter-web 等依赖都不用写版本号,parent 已经帮你管好了。


4. 仓库配置:repositories

对应 .npmrc 里的 registry。告诉 Maven 去哪里下载依赖。

xml 复制代码
<repositories>
    <!-- 阿里云镜像(国内推荐) -->
    <repository>
        <id>aliyun</id>
        <name>Aliyun Maven Repository</name>
        <url>https://maven.aliyun.com/repository/public</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

提示 :仓库配置一般放在 ~/.m2/settings.xml(全局配置),而不是每个项目的 pom.xml 里。


5. 构建配置:build

对应 package.jsonscripts + 构建工具配置。

xml 复制代码
<build>
    <!-- 最终打包出来的文件名 -->
    <finalName>my-app</finalName>

    <!-- 资源文件配置 -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!-- 打包时对资源文件中的变量进行替换 -->
            <filtering>true</filtering>
        </resource>
    </resources>

    <!-- 插件配置 -->
    <plugins>
        <!-- Maven 编译插件:指定 JDK 版本 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>

        <!-- Spring Boot 打包插件:打成可执行 jar -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

5.1 核心插件速查

插件 作用 类比前端
maven-compiler-plugin 编译 Java 代码,指定 JDK 版本 tsc 编译 TypeScript
maven-surefire-plugin 执行单元测试 jest / vitest
maven-jar-plugin 打成 jar 包 webpack 打包
maven-war-plugin 打成 war 包 -
spring-boot-maven-plugin 打成可执行的 Spring Boot jar -
maven-source-plugin 同时生成源码 jar 类似发布到 npm 时包含 source map

6. 多环境配置:profiles

对应前端在不同环境(开发、测试、生产)使用不同配置。

xml 复制代码
<profiles>
    <!-- 开发环境 -->
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <env>dev</env>
        </properties>
    </profile>

    <!-- 生产环境 -->
    <profile>
        <id>prod</id>
        <properties>
            <env>prod</env>
        </properties>
    </profile>
</profiles>

激活方式:

bash 复制代码
# 使用生产环境 profile
mvn clean package -P prod

打包时 src/main/resources 中的 application.yml 里的 ${env} 会被替换为 prod


7. 常用命令速查

命令 作用 类比 npm
mvn clean 清理 target 目录 rm -rf dist/
mvn compile 编译源代码 tsc / npm run build
mvn test 运行单元测试 npm test
mvn package 编译 + 测试 + 打包 npm run build
mvn install 打包 + 安装到本地仓库 npm link
mvn deploy 安装 + 发布到远程仓库 npm publish
mvn clean install -DskipTests 跳过测试直接安装 -
mvn dependency:tree 查看依赖树 npm ls
mvn spring-boot:run 直接启动 Spring Boot 应用 npm start

8. 完整 pom.xml 示例

一个典型的 Spring Boot 2.x(Java 8)项目的 pom.xml

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>

    <!-- 继承 Spring Boot 父 POM -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
    </parent>

    <!-- 项目坐标 -->
    <groupId>com.yourcompany</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>My Application</name>

    <!-- 属性 -->
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 依赖 -->
    <dependencies>
        <!-- Web 核心 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 数据库 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 构建 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

9. 前端 → Java 概念对照表

前端概念 Java (Maven) 概念
package.json pom.xml
package-lock.json mvn dependency:tree + <dependencyManagement>
node_modules 本地 Maven 仓库 ~/.m2/repository
npm install mvn install
npm publish mvn deploy
npm start mvn spring-boot:run
npm test mvn test
npm run build mvn package
dependencies <dependencies> + scope=compile
devDependencies <dependencies> + scope=testprovided
npm registry <repositories> / ~/.m2/settings.xml
npx mvn xxx:xxx(直接执行插件)

10. 写在最后

pom.xml 看着比 package.json 啰嗦很多,XML 嘛,天生就长。但理解了核心概念之后,无非就是:

  1. 项目坐标(groupId + artifactId + version)→ 这个包叫什么
  2. 依赖(dependencies)→ 这个包需要别人什么
  3. 版本管理(dependencyManagement)→ 大家统一用什么版本
  4. 构建(build + plugins)→ 这个包怎么编译、怎么打包
  5. 环境(profiles)→ 不同环境怎么切换

掌握这五点,日常开发基本不会懵。遇到问题就 mvn dependency:tree,90% 的依赖问题都能定位到。

祝转 Java 之路顺利! 更多请关注我的微信公众号,感谢!

相关推荐
彦为君1 小时前
JavaSE-11-网络编程(详细版)
java·前端·网络·ai·ai编程
IT策士1 小时前
Django 从 0 到 1 打造完整电商平台:收货地址管理
后端·python·django
HjhIron1 小时前
从三件套到模块化:前端开发的底层思维
前端·后端
yingyima1 小时前
Kubernetes CronJob 速查手册:核心语法与实战示例
前端
前端市界1 小时前
在阿里云 Docker 中管理 MySQL 8.0:常用命令与 Docker Compose 最佳实践
后端
麻雀飞吧1 小时前
TqWebHelper 本地监控:图表不刷新与端口冲突排查
前端·python
用户52438855928871 小时前
拆解Vue2源码-01 reactive
前端
咖啡八杯2 小时前
微信小程序人脸认证1.0迁移2.0
后端·微信小程序
甘露s2 小时前
JWT Token 机制设计演进:从单 Token 到企业级认证体系
后端·http·web