Maven

1. Maven是什么?

  • 基本概念
    Maven是Apache基金会的开源项目管理和构建自动化工具,使用POM(Project Object Model) 文件描述项目结构、依赖关系和构建配置。

  • 是否专门用于Java?
    主要定位:主要用于Java项目
    可扩展性:通过插件可支持其他语言(Scala、Groovy、Kotlin等)
    生态系统:虽然不限于Java,但在Java生态中最为成熟

  • 核心功能

    1
    2
    3
    4
    5
    ├── 依赖管理(Dependency Management)
    ├── 项目构建(Build Lifecycle)
    ├── 统一项目结构(Standard Directory Layout)
    ├── 插件体系(Plugin Architecture)
    └── 仓库管理(Repository)
  • Maven依赖的本质

    • 通过pom.xml引入的依赖,默认下载的是已编译的JAR包,主要包含:
      内容 说明 是否必须
      .class文件 已编译的字节码(人类可读的.java源代码文件编译而来) ✅ 必须,用于运行
      pom.xml 依赖的元数据 ✅ 必须,用于传递依赖解析
      源代码(.java) 可选,用于调试 ❌ 可选,IDE可单独下载
      javadoc API文档 ❌ 可选,IDE可单独下载
    • 依赖获取过程
      1
      2
      3
      4
      5
      6
      // pom.xml中的依赖声明
      <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>31.1-jre</version>
      </dependency>
    • 实际下载的文件
      1
      2
      3
      4
      5
      6
      7
      ~/.m2/repository/com/google/guava/guava/31.1-jre/
      ├── guava-31.1-jre.jar // 主要JAR,包含.class文件
      ├── guava-31.1-jre.pom // 该依赖的pom文件
      ├── _remote.repositories // 仓库信息
      └── 可能还有:
      ├── guava-31.1-jre-sources.jar // 源代码
      └── guava-31.1-jre-javadoc.jar // 文档

2. Maven基本命令

常用命令速查表

命令 功能 说明
mvn clean 清理项目 删除target目录
mvn compile 编译源码 生成target/classes
mvn test 运行测试 执行src/test下的测试
mvn package 打包项目 生成jar/war包
mvn install 安装到本地仓库 mvn package + 将jar安装到本地 ~/.m2/repository
mvn deploy 部署到远程仓库 发布到Nexus/Artifactory
mvn clean install 清理并安装 常用组合命令
mvn dependency:tree 查看依赖树 分析依赖关系
mvn spring-boot:run 运行Spring Boot 需要对应插件

Maven生命周期阶段

A[clean] –> B[validate] –> C[compile] –> D[test] –> E[package] –> F[verify] –> G[install] –> H[deploy]

1. mvn compile - 编译阶段

相当于:执行 javac 编译源代码

1
2
3
4
5
6
7
8
9
10
11
12
# 实际操作
# 1. 编译主代码
javac -cp "所有依赖的jar" -d target/classes src/main/java/**/*.java
# 2. 处理资源文件
cp src/main/resources/** target/classes/

# 生成目录结构
target/
├── classes/ # 编译输出的.class文件
│ ├── com/example/Main.class
│ └── application.properties
└── generated-sources/ # 生成的代码(如有)

当您运行 mvn compile时,Maven 会:
解析依赖:读取 pom.xml 中的
下载依赖:从远程仓库下载到本地 ~/.m2/repository/
构建依赖图:处理传递依赖
关键点:Maven 管理的这些依赖是已经编译好的 .class 文件(JAR 包),不是 .java 文件。

然后 Maven 会:
编译您的代码:src/main/java/下的 .java 文件
使用依赖:编译时将下载的依赖 JAR 加入 classpath
打包:将您的 .class 文件 + 资源文件打包

todo:那么打包的时候到底保护包含依赖?我自己的源代码编译 .class + 依赖包的 .class ??

2. mvn package - 打包阶段

相当于根据packaging类型不同,将编译结果打包成可分发的格式(注意:普通mvn package生成的jar不包含依赖!依赖需要单独配置)

1
2
3
4
5
6
<!-- pom.xml中指定打包类型 -->
<packaging>jar</packaging> <!-- 默认值 -->
<!-- 或 -->
<packaging>war</packaging>
<!-- 或 -->
<packaging>pom</packaging>

打包过程

1
2
3
4
5
6
7
# 对于jar包:
jar cvf target/myapp-1.0.jar -C target/classes .

# 生成的jar内容:
# META-INF/MANIFEST.MF # 清单文件
# com/example/Main.class # 你的类
# application.properties # 资源文件

3. mvn install - 安装阶段

mvn install 做了两件事:
1 执行之前所有阶段:validate → compile → test → package → verify → install
2 将当前项目的构建结果安装到本地仓库,安装位置 →

1
2
3
4
~/.m2/repository/com/yourcompany/yourapp/1.0.0/
├── yourapp-1.0.0.jar # 打包的jar
├── yourapp-1.0.0.pom # 当前项目的pom.xml
└── yourapp-1.0.0-sources.jar # 源代码(如果生成)

命令组合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 标准开发流程
mvn clean compile
mvn test
mvn package

# 跳过测试
mvn clean install -DskipTests

# 指定配置文件
mvn clean install -Pprod

# 查看帮助
mvn help:effective-pom
mvn help:describe -Dcmd=package

3. 打包Java服务为可运行JAR

三种打包方式对比

方式 插件 特点 适用场景
普通JAR maven-jar-plugin 不包含依赖 库项目
Fat JAR maven-assembly-plugin 包含所有依赖 简单应用
可执行JAR spring-boot-maven-plugin Spring Boot专用 Spring Boot应用
Shadow JAR maven-shade-plugin 重命名包解决冲突 复杂依赖

Spring Boot项目(最常用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- pom.xml -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.MainApplication</mainClass>
<!-- 包含依赖 -->
<layout>JAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
1
2
3
4
# 打包命令
mvn clean package
# 运行
java -jar target/your-app-1.0.0.jar

完整构建流程示例

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
my-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ └── App.java
│ │ └── resources/
│ │ └── config.properties
│ └── test/
│ └── java/
│ └── com/example/
│ └── AppTest.java
├── target/ # 构建输出目录
└── pom.xml

执行流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 清理 + 编译
mvn clean compile
# 生成: target/classes/ 目录

# 2. 运行测试
mvn test
# 生成: target/test-classes/ 和 target/surefire-reports/

# 3. 打包
mvn package
# 生成: target/my-project-1.0.jar

# 4. 安装到本地仓库
mvn install
# 生成: ~/.m2/repository/com/example/my-project/1.0/

4. IDEA中使用Maven与问题解决

IDEA Maven配置位置

1
File → Settings → Build, Execution, Deployment → Build Tools → Maven

常用操作

  1. 刷新依赖:Maven工具窗口的刷新按钮 🔄
  2. 执行命令:双击生命周期中的阶段
  3. 查看依赖图:右键项目 → Show Dependencies
  4. 排除冲突:在依赖树上右键排除

问题分类

  1. Import报红
    本地仓库缺失
    版本冲突
    网络问题
  2. 编译失败
    依赖下载不全
    编译版本不匹配
  3. 运行时异常
    依赖冲突
    ClassNotFound

解决方案

  1. 点击刷新按钮
  2. 仍未解决,检查网络–> 清除本地仓库–> 清理IDEA缓存 –> 检查依赖冲突 –> 重新导入项目

具体问题解决步骤

问题1:刷新按钮无效

症状:点击刷新后,依赖仍然报红

解决方案

  1. 强制刷新

    1
    2
    # 命令行执行
    mvn clean install -U

    -U 参数强制更新快照版本

  2. 删除本地仓库

    1
    2
    3
    4
    5
    # Windows
    rd /s /q %USERPROFILE%\.m2\repository

    # Mac/Linux
    rm -rf ~/.m2/repository
  3. 清除IDEA缓存

    1
    File → Invalidate Caches and Restart

问题2:依赖下载慢/失败

解决方案

  1. 配置阿里云镜像settings.xml):

    1
    2
    3
    4
    5
    6
    7
    8
    <mirrors>
    <mirror>
    <id>aliyun</id>
    <name>aliyun maven</name>
    <url>https://maven.aliyun.com/repository/public</url>
    <mirrorOf>central</mirrorOf>
    </mirror>
    </mirrors>
  2. IDEA配置镜像

    1
    2
    File → Settings → Build Tools → Maven
    修改 User settings file 为包含镜像的settings.xml

问题3:依赖冲突

症状:NoSuchMethodError, ClassNotFoundException

排查命令

1
2
3
4
5
6
7
8
# 查看依赖树
mvn dependency:tree

# 查看冲突
mvn dependency:tree -Dverbose

# 分析依赖
mvn dependency:analyze

IDEA可视化排查

  1. 右键项目 → Analyze → Analyze Dependencies
  2. 查看冲突标记(红色)

解决冲突示例

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>com.example</groupId>
<artifactId>problematic-lib</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>conflict-group</groupId>
<artifactId>conflict-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>

问题4:版本不兼容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 统一管理版本 -->
<properties>
<spring.version>5.3.23</spring.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

IDEA Maven工具窗口使用技巧

1. 快速操作

图标 功能 快捷键
🔄 重新导入所有Maven项目 Ctrl+Shift+O
🏃 运行Maven目标 右键→Run Maven
📊 显示依赖图 右键→Show Dependencies
🧹 执行clean 双击Lifecycle→clean

2. 配置文件切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- pom.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>

在IDEA Maven工具窗口的Profiles中勾选激活。

终极解决方案清单

当遇到顽固依赖问题时,按顺序执行:

  1. 第一步:清理缓存

    1
    mvn clean install -U
  2. 第二步:删除本地仓库对应目录

    1
    2
    # 删除有问题依赖的目录
    rm -rf ~/.m2/repository/com/example/problem-dependency
  3. 第三步:IDEA完全清理

    • File → Invalidate Caches and Restart
    • 删除项目下的 .idea 目录和 *.iml 文件
    • 重新导入
  4. 第四步:检查Maven配置

    1
    2
    3
    4
    5
    # 查看有效POM
    mvn help:effective-pom

    # 查看有效设置
    mvn help:effective-settings
  5. 第五步:网络代理检查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- settings.xml 配置代理 -->
    <proxies>
    <proxy>
    <id>optional</id>
    <active>true</active>
    <protocol>http</protocol>
    <host>proxy.company.com</host>
    <port>8080</port>
    </proxy>
    </proxies>

预防措施

  1. 使用依赖锁定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>3.2.1</version>
    <executions>
    <execution>
    <id>enforce</id>
    <configuration>
    <rules>
    <dependencyConvergence/>
    </rules>
    </configuration>
    <goals>
    <goal>enforce</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
  2. 定期清理本地仓库

    1
    2
    # 清理失败下载
    find ~/.m2/repository -name "*.lastUpdated" -delete
  3. 使用CI/CD环境验证
    在Jenkins/GitHub Actions中设置定期构建,提前发现问题。

常见错误代码与解决

错误代码 含义 解决方案
501 HTTPS Required 仓库需要HTTPS 更新settings.xml,使用https仓库
401 Unauthorized 认证失败 配置正确的server认证
Could not transfer artifact 网络/权限 检查网络,清理.lastUpdated文件
No compiler is provided JDK配置错误 配置JAVA_HOME,或在pom中指定javac

高级技巧

  1. 离线模式(网络不稳定时)

    1
    mvn clean install -o
  2. 跳过测试

    1
    2
    3
    mvn clean install -DskipTests
    # 或
    mvn clean install -Dmaven.test.skip=true
  3. 多线程构建

    1
    mvn clean install -T 4
  4. 调试模式

    1
    mvn -X clean install