[Buy Me a Java] Maven 快速上手指南

2024-10-15 | From java series.

Maven 是一个项目管理工具,可以通过配置文件(pom.xml)来管理项目的构建、报告和文档。

参考资料:

https://www.bilibili.com/video/BV1uApMeWErY

https://www.nosuchfield.com/2023/06/16/Maven-Details/

Maven 的生命周期

Maven 使用生命周期(lifecycle)表示软件开发和构建的流程,并总结出了三套默认的生命周期。

  • clean:清理项目
  • default:构建项目
  • site:构建项目站点

每个生命周期内又由多个阶段(phase)组成。phase 的执行有先后顺序的概念。在执行某个 phase 时,会按顺序从这个 lifecycle 最开始的 phase 开始执行,当上一个 phase 执行完成后会开始继续执行下一个 phase,一直执行到当前指定的 phase 结束。

这里关注几个常用的 phase。

default 的阶段用途
compile编译项目主源码,编译 src/main/java 目录内的 Java 文件到输出主 classpath 目录,如 idea 中生成的 target 文件夹
test执行单元测试
package将编译好的代码打包成可发布的格式,如 jar
install将打包好的文件安装到本地仓库
deploy将打包好的文件发布到远程仓库

简单来说就是 编译 -> 测试 -> 打包 -> 安装 | 发布 这一套流程。

如果是在 idea 中,点击右侧 M 按钮,点击 Lifecycle 即可看到相关选项。或者在命令行中执行相关命令可以得到同样效果。

配置文件 pom.xml

这是一个新建的 maven 项目的配置文件 pom.xml,POM 是 Project Object Model 的缩写,翻译过来就是项目对象模型。

<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.insorker</groupId>
  <artifactId>maven-test</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>maven-test</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

项目相关的配置如下

元素含义
groupId项目所属的组织或公司名
artifactId项目名
version项目的版本
name项目的可读名称,非必须
description项目的描述,非必须
packaging项目的打包方式,非必须,默认为 jar

<properties> 标签可以定义一些常量,比如定义某个通用的版本号,避免后续修改版本号时重复修改多次。

<properties>
  <mybatis.spring>2.2.0</mybatis.spring>
</properties>

<dependencies>
  <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>${mybatis.spring}</version>
  </dependency>
  ...
</dependencies>

<dependencies> 标签定义了项目相关的依赖,其中某个具体的依赖包裹在 <dependency> 标签中。相关的元素含义基本同上所述,这里详细描述一下新增的 scope

scope 表示依赖的作用范围,分为 test、compile、provided 和 runtime。即依赖产生作用的不同的 classpath。

scope含义
compile如果不指定就使用 compile 选项,代表编译依赖范围。使用这个配置的依赖范围的 maven 依赖,在编译、测试和运行的时候这个依赖都有效。例如 spring-code。
test依赖指对测试文件生效,如,junit 在 src 文件夹中不能 import。
provided依赖对编译和测试 classpath 有效,对运行时 classpath 无效。例如 servlet-api,运行时 tomcat 会提供。
runtime运行时依赖范围,对测试和运行 classpath 有效,对编译时无效。例如 JDBC 驱动,代码编译的时候只需要接口,实现只在真正运行时才需要。即 SPI(Service Provider Interface)机制下常用。

仓库 & 坐标

Maven 通过仓库管理 jar 包,方便项目的下载或引用。共有三种仓库,分别是本地仓库、私服仓库和中央仓库。

一般项目依赖会从中央仓库进行下载,如果配置了私服仓库则会从私服仓库下载。下载好的依赖会存储在本地仓库中,本地仓库是电脑上的一个目录,项目使用的依赖可以从对应的路径找到对应的 jar 包。

配置文件 pom.xml 这一节中已经提到过了 groupIdartifactIdversion 这三个概念。通过这三个信息就如同 3 维坐标轴一样确定了一个唯一对应的依赖。

通过中央仓库,即 https://mvnrepository.com/ ,从中找到具体的依赖,选中某个版本(可以参考右侧的选择率),复制代码添加到 pom.xml 中即可添加依赖。

依赖冲突

在 idea 中查看依赖,可以发现某个依赖 A 可能依赖了某个依赖 B,依赖 C 也同时依赖了依赖 B,但是版本不同,这就产生了依赖冲突。但是不必担心,maven 会自动选择某个依赖,选择顺序为

  • 最短路径:路径最短,深度最浅的依赖优先选择
  • 顺序选择:按从上到下的顺序选择依赖

当然也可以手动选择依赖的版本。具体方法可以通过添加 <exclusion> 标签或 <optional> 标签实现,这里不再赘述。

父子工程

Maven 完全支持多级的父子工程结构。父项目通过 <modules> 标签管理子模块,如

<modules>
  <module>m-a</module>
  <module>m-b</module>
  <module>m-c</module>
</modules>

子项目通过 <parent> 标签从父项目继承配置。

<parent>
  <groupId>com.insorker</groupId>
  <artifactId>maven-test</artifactId>
  <version>1.0-SNAPSHOT</version>
</parent>

默认继承所有 <dependencies><scope> 为 compile 的依赖,但是一般为了方便管理,在父项目的配置文件中使用 <dependencyManagement> 标签管理,这样子模块可以通过配置指定具体继承的依赖,配置时无需指明版本号。