前端视角 Java Web 入门手册 1.2:使用 Maven 管理依赖

371 阅读6分钟

Maven 是一个强大的 Java 项目管理和构建工具,它简化了项目的构建过程,管理项目的依赖,并提供统一的项目结构和生命周期管理。主要功能包括:

  • 依赖管理:自动下载和管理项目所需的第三方库(如JAR文件)
  • 项目构建:编译源代码、运行测试、打包项目、生成文档等
  • 项目管理:统一的项目结构和配置,简化团队协作

Google 推出的 Gradle 是 Maven 主要竞对,支持使用 Groovy 或 Kotlin DSL 编写构建脚本,非常灵活。同时 Gradle 支持差量处理、任务并行等特性,使其拥有更高的性能

Maven 与前端工具对比

如果熟悉前端工程化工具,可以将 Maven 看作 Java 生态中的类似工具:

前端工具Maven
npm + webpackMaven
package.jsonpom.xml
node_modulesLocal Repository
registryCentral Repository
  • pom.xml:类似于前端的 package.json,用于定义项目依赖、插件和构建配置
  • Local Repository:本地存储已经下载的依赖包,类似于 node_modules
  • Central Repository:Maven的中央仓库,用于存储和下载各种Java依赖,类似于 npm 的 registry

Maven 的核心概念

项目对象模型 POM

POM(Project Object Model) 是Maven项目的核心,通过 pom.xml 文件进行配置。POM文件定义了项目的结构、依赖、插件、构建目标等。

<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.example</groupId>
  <artifactId>my-web-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <dependencies>
    <!-- 依赖项在此添加 -->
  </dependencies>

  <build>
    <plugins>
      <!-- 插件在此添加 -->
    </plugins>
  </build>
</project>

依赖管理

Maven通过在POM文件中定义依赖来自动管理第三方库,Maven 会从中央仓库或指定的仓库下载这些依赖,并将其添加到项目中

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.1.0</version>
    </dependency>
    
    <!-- JUnit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.9.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Java 可复用的软件包发布为 JAR(Java Archive)格式,在 Maven 中管理的 JAR 其唯一标识由三个部分组成

  • groupId:类似 Java 的包名,通常是公司或者组织的名称
  • artifactId:类似 Java 类名,通常是项目名称
  • version:版本号,一般使用 x.y.z 格式

在 Node.js 一般会用 x.z.z-beta.3 这种形式来表示、指定安装开发中的版本,Java 中则使用 z.y.z-SNAPSHOT 的方式,SNAPSHOT 可以不修改版本号反复修改、发布

Maven 不会对 SNAPSHOT 版本包缓存,每次构建都会重新下载。部分团队会利用此特性来配置类似安全相关的,这类需要使用最新版本的 JAR 包

central.sonatype.dev/ 上可以方便搜索 Maven 中心仓库的包信息及引用方式

Repositories

Maven 使用仓库来存储和获取依赖,主要有:

  • 中央仓库(Central Repository) :默认的官方仓库,包含了大量的开源Java依赖
  • 本地仓库(Local Repository) :本机上的缓存位置,默认位于 ~/.m2/repository
  • 远程仓库(Remote Repositories) :公司内部或第三方的仓库,用于存储特定的依赖

安装 Maven

  1. 下载 Maven:访问 Maven 官方下载页,下载最新版本的二进制压缩包(例如 apache-maven-3.8.6-bin.zipapache-maven-3.8.6-bin.tar.gz

  2. 解压缩:将下载的压缩包解压到你选择的目录(例如 C:\Program Files\Apache\Maven/usr/local/apache-maven)。

  3. 配置环境变量:将 Maven 的 bin 目录添加到系统的 PATH 环境变量中。

    • Windows

      • 右键“此电脑” > “属性” > “高级系统设置” > “环境变量”。
      • 在“系统变量”中找到 Path,点击“编辑”,添加 C:\Program Files\Apache\Maven\apache-maven-3.8.6\bin
    • macOS/Linux

      • 编辑 ~/.bash_profile, ~/.zshrc~/.bashrc 文件,添加export PATH=/usr/local/apache-maven/apache-maven-3.8.6/bin:$PATH

运行命令 mvn --version验证

Maven 中央仓库下载可能会比较慢,修改 maven 安装目录/conf/setting.xml,在 mirroes 节点添加以下内容,可以切换为阿里云镜像

<mirror>
   <id>aliyunmaven</id>
   <mirrorOf>*</mirrorOf>
   <name>阿里云公共仓库</name>
   <url>https://maven.aliyun.com/repository/public</url>
</mirror> 

Maven 项目结构

使用 IntelliJ IDEA 可以很方便创建一个 Maven 项目

maven-project
├── pom.xml // 项目描述文件,类似 Node.js 项目的 package.json
├── src
│   ├── main
│   │   ├── java // Java 源码
│   │   └── resources // 资源文件
│   └── test
│       ├── java
│       └── resources
└── target // 编译、打包生成的文件

在 pom.xml 配置项目依赖

在项目 pom.xml dependencies 节点中添加 dependency 节点,设置 groupId、artifactId、version 可以添加依赖,在 IntelliJ IDEA 中使用 Maven 工具可以快速把依赖下载到项目 External Libraries

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>my-web-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.1.0</version>
        </dependency>
        
        <!-- JUnit 5 for Testing -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.11.4</version>
            <scope>test</scope>
        </dependency>
        
        <!-- 其他依赖项 -->
    </dependencies>
    
    <!-- 构建插件可以在此添加 -->
</project>

有时候会发现部分模块定义版本号为 999-not-exist,主要是为了加载一个 Maven 中不存在的版本号,从而强制排除项目对该包的依赖

使用 scope 指定 JAR 使用范围

可以注意到有些包在配置依赖时候会添加scope

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
</dependency>

Maven 构建生命周期是一个有序的阶段序列,这些阶段会依次执行,以完成项目的构建和部署等操作。主要包括以下几个重要阶段:

  1. 清理(Clean) :删除之前构建产生的输出文件,确保构建环境的干净

    • 命令mvn clean
    • 主要操作:删除 target 目录及其内容,该目录通常包含编译的类文件、打包文件、测试报告等。
  2. 编译(Compile) :将源代码编译为字节码

    • 命令mvn compile
    • 主要操作:将 src/main/java 目录下的 Java 源代码编译为字节码文件,并存储在 target/classes 目录下。
  3. 测试(Test) :运行单元测试,确保代码的正确性

    • 命令mvn test
    • 主要操作
      • 编译 src/test/java 中的测试代码。
      • 使用 JUnit 或 TestNG 等测试框架运行测试。
      • 测试结果存储在 target/surefire-reports 目录下。
  4. 打包(Package) :将编译后的类文件和资源文件打包成可分发的文件格式

    • 命令mvn package

    • 主要操作

      • 对于 Java 项目,将 target/classes 目录下的文件打包成 .jar 文件。
      • 对于 Web 项目,可能打包成 .war 文件。
      • 对于 Spring Boot 项目,使用 Spring Boot Maven 插件可将项目打包成可执行的 .jar.war 文件。
  5. 安装(Install) :将打包好的文件安装到本地 Maven 仓库中,以便其它项目使用

    • 命令mvn install
    • 主要操作:将 target 目录下生成的 .jar.war 文件复制到本地 Maven 仓库(通常位于用户的 ~/.m2/repository 目录)。
  6. 部署(Deploy) :将打包好的文件部署到远程 Maven 仓库,以供团队或组织内的其他成员使用

    • 命令mvn deploy
    • 主要操作:将项目的构建产物上传到远程 Maven 仓库,需要在 pom.xml 中配置远程仓库的信息。

有些命令执行多个阶段

  • mvn package: 会依次执行 compile、test、package 阶段
  • mvn install:会依次执行 compile、test、package、install 阶段
  • mvn verify:会执行 validate、compile、test、package、integration-test、verify 阶段

不同 jar 在项目不同阶段起作用, 可以指定包生效的阶段

scope说明示例
compile默认值,依赖包会参与项目的编译、测试、打包、运行阶段log4j
provided和 compile 类似,因为内容由 JDK 或者服务器等提供,不参与打包servlet-api
runtime不需要参与编译,但运行、打包时需要,一般是因为代码中仅仅使用了接口mysql
test仅在测试阶段被使用,包括测试代码的编译、执行junit
system和 provided 类似,但依赖不从 maven 加载,而是从系统本地获取
import表示从其它 pom 导入依赖,相当于引用,解决项目只能设置一个父项目的限制问题

上文中 junit 的配置,表示该 jar 只在测试阶段被使用