强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Java 完全指南 / 20 - Maven:POM、依赖管理、生命周期、插件、私服

20 - Maven:POM、依赖管理、生命周期、插件、私服

POM 文件结构

<?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
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 父 POM(继承) -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>

    <!-- 项目坐标 -->
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>My Application</name>
    <description>A demo application</description>

    <!-- 属性 -->
    <properties>
        <java.version>21</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <spring-boot.version>3.2.0</spring-boot.version>
    </properties>

    <!-- 依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

依赖管理

依赖范围(Scope)

Scope编译测试运行打包示例
compile(默认)Spring Core
providedServlet API
runtimeJDBC 驱动
testJUnit
system本地 JAR(不推荐)
import----BOM 导入

依赖传递与排除

<dependencies>
    <!-- 排除传递依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <exclusions>
            <exclusion>
                <groupId>com.zaxxer</groupId>
                <artifactId>HikariCP</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- 可选依赖 -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<!-- 版本统一管理(dependencyManagement) -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>2.16.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

生命周期

三个内置生命周期

生命周期阶段(按顺序执行)
cleanpre-clean → clean → post-clean
defaultvalidate → compile → test → package → verify → install → deploy
sitepre-site → site → post-site → site-deploy
# 常用命令
mvn clean              # 清理 target/
mvn compile            # 编译
mvn test               # 运行测试
mvn package            # 打包 JAR/WAR
mvn install            # 安装到本地仓库
mvn deploy             # 部署到远程仓库
mvn clean install      # 清理 + 安装(最常用)

# 依赖相关
mvn dependency:tree    # 依赖树
mvn dependency:analyze # 分析未使用/未声明的依赖
mvn versions:display-dependency-updates  # 检查依赖更新

# 跳过测试
mvn package -DskipTests           # 跳过执行测试
mvn package -Dmaven.test.skip=true # 跳过编译和执行测试

常用插件

<build>
    <plugins>
        <!-- 编译器插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.12.1</version>
            <configuration>
                <source>21</source>
                <target>21</target>
                <compilerArgs>
                    <arg>--enable-preview</arg>
                </compilerArgs>
            </configuration>
        </plugin>

        <!-- Surefire 测试插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.2.3</version>
            <configuration>
                <includes>
                    <include>**/*Test.java</include>
                </includes>
            </configuration>
        </plugin>

        <!-- Exec 执行插件 -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <mainClass>com.example.App</mainClass>
            </configuration>
        </plugin>

        <!-- JaCoCo 代码覆盖率 -->
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.11</version>
            <executions>
                <execution>
                    <goals><goal>prepare-agent</goal></goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>test</phase>
                    <goals><goal>report</goal></goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

多模块项目

parent-project/
├── pom.xml                    <!-- 父 POM -->
├── module-common/
│   ├── pom.xml
│   └── src/
├── module-service/
│   ├── pom.xml
│   └── src/
└── module-web/
    ├── pom.xml
    └── src/
<!-- 父 pom.xml -->
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<modules>
    <module>module-common</module>
    <module>module-service</module>
    <module>module-web</module>
</modules>
<!-- 子模块 pom.xml -->
<parent>
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>1.0.0</version>
</parent>
<artifactId>module-web</artifactId>

<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>module-common</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

私服配置

<!-- pom.xml 配置仓库 -->
<distributionManagement>
    <repository>
        <id>releases</id>
        <url>https://nexus.example.com/repository/releases/</url>
    </repository>
    <snapshotRepository>
        <id>snapshots</id>
        <url>https://nexus.example.com/repository/snapshots/</url>
    </snapshotRepository>
</distributionManagement>
<!-- ~/.m2/settings.xml 认证 -->
<servers>
    <server>
        <id>releases</id>
        <username>admin</username>
        <password>加密密码</password>
    </server>
</servers>

⚠️ 注意事项

  1. SNAPSHOT 版本不稳定 — 生产环境不要依赖 SNAPSHOT 版本。
  2. 依赖冲突 — Maven 使用"最近优先"策略,可能不是期望的版本。
  3. 本地仓库清理.m2/repository 可能很大,定期清理。
  4. 插件版本锁定 — 不要省略插件版本号,避免不同环境行为不一致。

💡 技巧

  1. 查看依赖树排查冲突

    mvn dependency:tree -Dincludes=jackson-core
    
  2. 使用 mvnw Maven Wrapper — 团队统一版本:

    mvn wrapper:wrapper -Dmaven=3.9.6
    ./mvnw clean install
    
  3. Profile 切换环境

    <profiles>
        <profile>
            <id>prod</id>
            <properties><db.url>jdbc:mysql://prod-server/db</db.url></properties>
        </profile>
    </profiles>
    
    mvn package -Pprod
    

🏢 业务场景

  • 企业多模块项目: 父 POM 统一管理依赖版本,子模块按职责划分。
  • CI/CD: mvn clean deploy 自动构建并发布到 Nexus 私服。
  • 微服务架构: 每个服务独立 Maven 项目,共享 parent POM。

📖 扩展阅读