科普文:一文搞懂Maven

概叙

什么是Maven?

官网:Maven – Maven中文网 官网

  • Maven(读作“马文”)是一个软件项目管理和构建工具,主要用于Java项目。它简化了项目的构建、依赖管理和项目信息管理。
  • Maven 是一个意第绪语单词,意思是 知识的积累器,最初是为了简化 Jakarta Turbine 项目的构建过程。有几个项目,每个项目都有自己的 Ant 构建文件,但都略有不同。JAR 已签入 CVS。我们需要一种构建项目的标准方法、项目组成的清晰定义、发布项目信息的简单方法以及跨多个项目共享 JAR 的方法。
  • Maven基于项目对象模型 (POM) 的概念,Maven 可以通过中央信息来管理项目的构建、报告和文档。

maven的环境变量

Maven核心原理:项目对象模型 (Project Object Model)

  • 项目对象模型(POM):Maven通过一个XML文件pom.xml来描述项目的基本信息、依赖、插件和构建流程。Maven 包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段 (phase)中插件(plugin)目标(goal)的逻辑。
  • 构建生命周期:Maven定义了一个标准化的构建生命周期,包括编译、测试、打包、部署等阶段。开发者可以通过执行生命周期的不同阶段来完成项目的构建和部署。
  • 依赖管理:Maven通过集中仓库管理项目的依赖,自动下载和管理项目所需的库和插件,避免了手动管理依赖的麻烦。
    <!-- 依赖关系 -->
    <dependencies>
    <!-- 此项目运行使用 junit,所以此项目依赖 junit -->
    <dependency>
    <!-- junit 的项目名称 -->
    <groupId>junit</groupId>
    <!-- junit 的模块名称 -->
    <artifactId>junit</artifactId>
    <!-- junit 版本 -->
    <version>4.9</version>
    <!-- 依赖范围:单元测试时使用 junit -->
    <scope>test</scope>
    </dependency>

  • 插件体系:Maven的功能主要通过插件来扩展,用户可以根据项目需求选择和配置不同的插件,完成自定义的构建任务。

Maven工作流程

使用maven完成项目的构建,项目构建包括:清理,编译,部署等过程,maven将这些过程规范为一个生命周期,如下所示是生命周期的各阶段

maven 通过执行一些简单命令即可实现上边生命周期的各各过程,比如执行 mvn compile 执行编译、 执行 mvn clean 执行清理。 

  • 解析POM文件:Maven读取pom.xml文件,解析出项目的依赖、插件和构建配置。
  • 下载依赖:根据pom.xml中声明的依赖,Maven从本地仓库或远程仓库下载所需的依赖项。
  • 执行构建生命周期:用户通过命令(如mvn clean package)执行Maven的构建生命周期阶段,Maven根据生命周期阶段执行相应的插件目标,完成诸如编译、测试、打包等操作。
  • 生成构建结果:根据执行的生命周期阶段,Maven生成相应的输出,如JAR文件、WAR文件等。
  • scope依赖作用域:也可以称作依赖范围:maven中的的依赖,会根据场景和所处阶段发生变化。scope属性有五种:

    扫描二维码关注公众号,回复: 17640427 查看本文章

system:不推荐使用,使用system作用域不会去本地仓库寻找依赖,要指定本地绝对路径。 

Maven的优缺点

  1. 优点
  • 标准化的项目管理:Maven通过标准化的POM文件和构建生命周期,简化了项目管理和构建过程,降低了开发者对构建工具的依赖。
    • 强大的依赖管理:Maven通过仓库管理依赖,自动化依赖的下载、安装和管理,简化了依赖冲突的解决。
    • 丰富的插件生态:Maven拥有庞大且活跃的插件生态,几乎可以扩展任何构建需求,支持自定义构建流程。
    • 跨平台支持:Maven可以在任何操作系统上运行,支持多种构建环境。
    • 支持多模块项目:Maven非常适合大型多模块项目,通过统一的构建和管理方式,提升了开发效率。
  1. 缺点
    • 学习曲线陡峭:对于新手来说,Maven的概念和配置可能较为复杂,需要时间和实践来掌握。
    • 配置复杂性:虽然Maven通过POM文件简化了项目配置,但在复杂项目中,pom.xml文件可能变得冗长和难以维护。
    • 性能问题:在处理非常大的项目或复杂的依赖关系时,Maven的性能可能会显得不够理想,构建时间较长。
    • 版本管理的挑战:在多模块项目中,依赖版本的管理可能较为复杂,需要仔细规划和维护。

Maven的目标

Maven 的主要目标是让开发人员在最短的时间内了解开发工作的完整状态。为了实现这一目标,Maven 处理了几个需要关注的领域:

  • 使构建过程变得简单
  • 提供统一的构建系统
  • 提供优质项目信息
  • 鼓励更好的开发实践

Maven约定配置

Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。如下所示:

目录 目的
${basedir} 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources 项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${basedir}/target/classes 编译输出目录
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository Maven默认的本地仓库目录位置

使构建过程变得简单

虽然使用 Maven 并不能消除了解底层机制的需要,但 Maven 确实使开发人员免于了解许多细节。

提供统一的构建系统

Maven 使用其项目对象模型 (POM) 和一组插件来构建项目。一旦熟悉了一个 Maven 项目,您就知道所有 Maven 项目是如何构建的。这可以在浏览许多项目时节省时间。

提供优质项目信息

Maven 提供有用的项目信息,这些信息部分取自 POM,部分从项目源生成。例如,Maven可以提供:

  • 直接从源代码管理创建的更改日志
  • 交叉引用来源
  • 由项目管理的邮件列表
  • 项目使用的依赖项
  • 包括覆盖率的单元测试报告

第三方代码分析产品还提供 Maven 插件,将其报告添加到 Maven 给出的标准信息中。

Maven插件的分类和功能

Maven – Available Plugins

Maven的核心是一个插件执行框架;所有工作都是由插件完成的。

‌Available Plugins‌指的是在Maven中可用的插件集合,这些插件可以帮助开发者完成各种构建、测试、打包、部署等任务。

Maven是一个项目管理和自动化构建工具,它通过插件机制来扩展功能。

寻找要执行的特定目标?

Maven插件可以分为核心插件和第三方插件:

  • 核心插件‌:这些是Maven自带的插件,如maven-compiler-plugin用于编译代码,maven-deploy-plugin用于部署项目等。
  • 第三方插件‌:由社区或第三方提供的插件,如spring-boot-maven-plugin用于Spring Boot项目的构建和运行。

此页列出了核心插件和其他插件。有构建插件和报告插件:

  • 构建插件Build plugins  :将在生成期间执行,并且应在<构建/>POM中的元素。
  • 报告插件Reporting plugins:将在站点生成期间执行,并且应在<报告/>POM中的元素。由于报告插件的结果是生成站点的一部分,因此报告插件应该国际化和本地化。您可以阅读更多关于我们插件的本地化以及您可以如何提供帮助。

下面是一些常用插件的列表:

插件 描述
clean 构建之后清理目标文件。删除目标目录。
compiler 编译 Java 源文件。
surefile 运行 JUnit 单元测试。创建测试报告。
jar 从当前工程中构建 JAR 文件。
war 从当前工程中构建 WAR 文件。
javadoc 为工程生成 Javadoc。
antrun 从构建过程的任意一个阶段中运行一个 ant 任务的集合。

要查看最新列表,请浏览Maven存储库,特别是 org/apache/maven/plugins子目录。(插件根据类似于标准Java包命名约定的目录结构进行组织)

插件 类型* 版本 发布日期 说明 源码库信息 问题跟踪
核心插件 对应于默认核心阶段(即清理、编译)的插件。他们也可能有多个目标。
清洁的 B类 3.3.1 2023-06-14 构建后进行清理。 吉特/github 吉拉·麦克林
编译器 B类 3.11.0 2023-02-14 编译Java源代码。 吉特/github Jira MCOMPILER公司
部署 B类 3.1.1 2023-03-21 将构建的工件部署到远程存储库。 吉特/github 吉拉·麦德普洛伊
故障保护 B类 3.1.2 2023-06-03 在隔离的类加载器中运行JUnit集成测试。 吉特/github Jira SUREFIRE公司
安装 B类 3.1.1 2023-03-21 将构建的工件安装到本地存储库中。 吉特/github 吉拉·明斯塔尔
资源 B类 3.3.1 2023-03-21 将资源复制到输出目录,以便包含在JAR中。 吉特/github 吉拉先生
网站 B类 2010年3月4日 2023-10-07 为当前项目生成站点。 吉特/github Jira MSITE公司
万无一失 B类 3.1.2 2023-06-03 在隔离的类加载器中运行JUnit单元测试。 吉特/github Jira SUREFIRE公司
验证器 B类 1.1 2015-04-14 对集成测试有用-验证特定条件的存在。 吉特/github 吉拉·MVERIFIER
包装类型/工具 这些插件与打包各自的工件类型有关。
耳朵 B类 3.3.0 2022-10-18 从当前项目生成EAR。 吉特/github 吉拉·梅厄
电子束 B类 3.2.1 2022-04-18 从当前项目构建EJB(和可选客户端)。 吉特/github 吉拉MEJB
罐子 B类 3.3.0 2022-09-12 从当前项目构建JAR。 吉特/github 吉拉MJAR
放射性核素 B类 3.0.0 2022-07-17 根据当前项目构建RAR。 吉特/github 吉拉MRAR
战争 B类 3.4.0 2023-06-11 从当前项目构建WAR。 吉特/github 吉拉MWAR
应用程序客户端/acr B类 3.1.0 2018-06-19 从当前项目构建一个JavaEE应用程序客户端。 吉特/github 吉拉MACR
阴影 B类 3.5.1 2023-09-21 从当前项目构建Uber-JAR,包括依赖项。 吉特/github 吉拉·姆沙德
来源 B类 3.3.0 2023-05-17 从当前项目构建一个source-JAR。 吉特/github Jira MSOURCES公司
jlink公司 B类 3.1.0 2020-12-28 构建Java运行时映像。 吉特/github Jira MJLINK公司
jmod公司 B类 3.0.0-α-1 2017-09-17 构建Java JMod文件。 吉特/github Jira MJMOD公司
报告插件 生成报告的插件在POM中配置为报告,并在站点生成生命周期中运行。
变更日志 R(右) 2.3 2014-06-24 从SCM生成最近更改的列表。 吉特/github 吉拉·麦昌格洛格
变化 B+R 2.12.1 2016-11-01 从问题跟踪器或更改文档生成报告。 吉特/github 吉拉·麦钱斯
代码检查 B+R 3.3.0 2023-05-19 生成Checkstyle报告。 吉特/github 吉拉·麦切克风格
多哈回合 B类 1.2 2015-03-17 从POM生成项目描述(DOAP)文件。 吉特/github 吉拉MDOAP
文件 B类 1.1 2015-04-03 文档检查器插件。 吉特/github Jira MDOCCK公司
java文档 B+R 3.6.0 2023-09-11 为项目生成Javadoc。 吉特/github 吉拉·玛卡瓦多克
jdeps公司 B类 3.1.2 2019-06-12 在项目上运行JDK的JDeps工具。 吉特/github Jira MJDEPS公司
jxr公司 R(右) 3.3.0 2022-08-16 生成源交叉引用。 吉特/github 吉拉JXR
链接检查 R(右) 1.2 2014-10-08 生成项目文档的Linkcheck报告。 吉特/github 吉拉·姆林切克
偏振模色散 B+R 3.21.0 2023-05-12 生成PMD报告。 吉特/github 吉拉MPMD
报告中的项目 R(右) 3.4.5 2023-06-03 生成标准项目报告。 吉特/github 吉拉MPIR
可靠的报告 R(右) 3.1.2 2023-06-03 根据单元测试的结果生成报告。 吉特/github Jira SUREFIRE公司
工具 默认情况下,这些是Maven提供的各种工具。
安特伦 B类 3.1.0 2022-04-18 从构建的一个阶段运行一组ant任务。 吉特/github 吉拉·曼特伦
人工制品 B类 3.5.0 2023-10-02 管理工件任务,如buildinfo。 吉特/github 吉拉·马蒂法特
原型 B类 3.2.1 2021-12-30 从原型生成一个框架项目结构。 吉特/github Jira建筑类型
装配 B类 3.6.0 2023-05-11 构建源代码和/或二进制文件的程序集(分发版)。 吉特/github 吉拉·马斯塞姆利
附属国 B+R 3.6.0 2023-05-19 相关性操作(复制、解压缩)和分析。 吉特/github 吉拉MDEP
强制执行人 B类 3.4.1 2023-09-07 环境约束检查(Maven版本、JDK等)、用户自定义规则执行。 吉特/github 吉拉·曼福塞
gpg(加仑/加仑) B类 3.1.0 2023-05-06 为工件和pom创建签名。 吉特/github 吉拉MGPG
帮助 B类 3.4.0 2023-03-14 获取有关项目工作环境的信息。 吉特/github 吉拉公共卫生部
调用程序 B+R 3.6.0 2023-06-11 运行一组Maven项目并验证输出。 吉特/github 吉拉·明沃克
震击者 B类 3.0.0 2018-11-06 签署或验证项目工件。 吉特/github Jira MJAR签名人
jderscan扫描 B类 3.0.0-α-1 2017-11-15 在项目上运行JDK的JDeprScan工具。 吉特/github 吉拉·梅杰普斯卡纳
补丁 B类 1.2 2015-03-09 使用gnu补丁工具将补丁文件应用于源代码。 吉特/github 吉拉·马奇
pdf格式 B类 1.6.1 2022-08-16 生成项目文档的PDF版本。 吉特/github 吉拉MPDF
插件 B类 3.9.0 2023-05-12 为源代码树中的任何mojo创建Maven插件描述符,以包含在JAR中。 吉特/github 吉拉·穆卢金
插件报告 R(右) 3.9.0 2023-05-12 为源代码树中的任何mojo创建插件文档。 吉特/github 吉拉·姆卢金
释放 B类 3.0.1 2023-05-30 发布当前项目-在SCM中更新POM和标记。 吉特/github 吉拉·梅勒莱斯
远程资源 B类 3.1.0 2023-05-08 将远程资源复制到输出目录以包含在工件中。 吉特/github Jira MRRESOURCES公司
供应链管理 B类 2.0.1 2023-05-15 对当前项目执行SCM命令。 吉特/github Jira供应链管理
scm发布 B类 3.2.1 2023-03-26 将Maven网站发布到scm位置。 吉特/github 吉拉MSCMPUB
编写脚本 B类 3.0.0 2021-03-01 Maven脚本插件根据JSR223封装了脚本API。 吉特/github Jira MSCRIPTING公司
阶段 B类 1 2015-03-03 协助发布阶段和推广。 吉特/github Jira MSTAGE公司
工具链 B类 3.1.0 2022-06-18 允许跨插件共享配置。 吉特/github 吉拉·姆托卡恩斯
包装器 B类 3.2.0 2023-03-09 下载并解压缩maven包装器发行版 吉特/github 吉拉·姆夫拉珀

*B类uild或R(右)报告插件

我们还提供了一些沙盒插件源存储库.

插件参考文档的先前存档版本包括位于此处.

提供最佳实践开发指南

Maven 旨在收集最佳实践开发的当前原则,并轻松引导项目朝该方向发展。

例如,单元测试的规范、执行和报告是使用 Maven 的正常构建周期的一部分。当前的单元测试最佳实践被用作指导方针:

  • 将测试源代码保存在单独但并行的源代码树中
  • 使用测试用例命名约定来定位和执行测试
  • 让测试用例设置其环境,而不是定制测试准备的构建

Maven 还协助项目工作流程,例如发布和问题管理。

Maven 还建议了一些关于如何布局项目目录结构的指南。一旦了解了布局,您就可以轻松导航使用 Maven 的其他项目。

虽然 Maven 对项目布局采取了固执己见的方法,但由于历史原因,某些项目可能不适合这种结构。虽然 Maven 被设计为能够灵活地满足不同项目的需求,但它无法在不影响其目标的情况下满足所有情况。

如果您的项目具有无法重组的不寻常构建结构,您可能必须放弃某些功能或完全放弃 Maven 的使用。

Maven的核心特性

  1. 标准化的项目结构

    • Maven要求项目遵循一种标准的目录结构,例如:
      src/main/java          # 源代码
      src/main/resources     # 资源文件 src/test/java          # 测试代码
      src/test/resources     # 测试资源文件
      pom.xml                # 项目描述文件
    • 这种标准化的结构使得开发者可以快速理解和导航项目结构,减少了项目间因为目录结构不一致带来的困扰。
  2. 依赖管理

    • Maven通过pom.xml文件声明项目依赖,自动完成依赖的下载、安装和管理。
    • 支持依赖的范围(scope)管理,如compile(编译范围,默认)、test(测试范围)、runtime(运行时范围)等,方便管理不同阶段所需的依赖。
    • 支持依赖的传递性,即如果项目A依赖于项目B,而项目B又依赖于项目C,Maven会自动将项目C的依赖包含进项目A的依赖中。
    • 提供依赖冲突解决机制,通过策略(如“最近的者优先”)解决依赖版本冲突的问题。
  3. 构建生命周期

    • Maven定义了一个标准化的构建生命周期,包括以下几个主要阶段:
      • validate: 验证项目是否正确,并且所有必要的信息都可用。
      • compile: 编译项目的源代码。
      • test: 使用合适的单元测试框架(如JUnit)运行测试。
      • package: 将编译好的代码打包成可分发的格式,如JAR、WAR。
      • verify: 运行任何检查来验证构建输出是否满足要求。
      • install: 将包安装到本地仓库,以便可以作为其他本地项目的依赖。
      • deploy: 将最终的包发送到远程仓库,供其他开发者或项目使用。
    • maven常用命令

      • mvn clean 清理,编译后的目录;

      • mvn compile 编译;只编译main目录,不编译test中代码;

      • mvn test-compile 编译test麻目录中代码;

      • mvn test 运行test里边代码测试;

      • web项目打成war包

      • mvn install 发布项目到本地仓库,在本地Repository中安装jar,供其他工程使用;

      • tomcat run 一键构建项目

      • mvn site 生成项目的相关文档和生成文档相关的元素,包括name,url,和description等。

  4. 插件体系

    • Maven的功能主要通过插件来实现,如maven-compiler-plugin用于编译代码,maven-surefire-plugin用于执行测试,maven-source-plugin用于生成源代码包等。
    • 用户可以通过配置插件,自定义构建过程,例如定义自定义的编译选项、测试配置等。
  5. 项目继承与多模块管理

    • Maven支持项目继承,一个父项目可以定义多个子项目,子项目继承父项目的依赖和插件配置,简化了项目间的配置管理。
    • 在多模块项目中,可以通过modules元素定义子模块,Maven允许对子模块进行统一的构建和管理。

Maven的分模块设计

  1. 多模块项目的结构

    • 多模块项目包含一个父项目和多个子项目,项目结构如下:
      parent-project/
        ├── pom.xml         # 父项目的POM文件
        └── module-A/
            ├── src/        # 模块A的源代码
            └── pom.xml    # 模块A的POM文件

    • 父项目的pom.xml文件中使用<modules>元素声明子模块:
      <modules>
          <module>module-A</module>
      </modules>
      
  2. 分模块设计的优势

    • 职责分离:将大型项目划分为多个独立的模块,每个模块负责不同的功能,提高代码的可维护性和复用性。
    • 独立管理:每个模块可以有自己的依赖和配置,彼此之间互不干扰。
    • 统一构建:通过Maven的多模块管理,可以对所有模块进行统一的构建、测试和打包,简化了多模块项目的管理。
    • 资源共享:模块之间可以共享父项目中的依赖和插件配置,减少重复的配置工作。
  3. 实现细节

    • 在多模块项目中,子模块的pom.xml文件继承父项目的groupIdversion,通过<parent>元素声明父项目:
      <parent>
          <groupId>com.example.parent</groupId>
          <artifactId>parent-project</artifactId>
          <version>1.0.0-SNAPSHOT</version>
      </parent>
      
    • 子模块可以定义自己独有的依赖和插件,父项目则定义所有模块共享的依赖和插件。

Maven的注意事项

  1. 合理管理依赖

    • 避免过多的依赖:尽量减少不必要的依赖,避免“依赖地狱”。
    • 统一依赖版本:通过父项目或依赖管理部分统一管理依赖版本,避免子模块间的依赖冲突。
    • 定期清理依赖:通过Maven的dependency:analyze插件,分析项目中的未使用依赖,并对其进行清理。
  2. 配置插件时注意配置正确性

    • 仔细阅读插件文档:在配置插件时,确保理解插件的功能和配置参数,避免由于配置错误导致的构建失败。
    • 避免过度自定义:尽量使用Maven的默认配置和生命周期,减少不必要的自定义配置,提高项目的可维护性。
  3. 注意仓库管理

    • 使用高速镜像仓库:配置Maven使用较快的仓库镜像,如Nexus、Alibaba’s public repository,提高依赖下载速度。
    • 管理本地仓库:定期清理本地仓库,避免旧版本的依赖占用过多磁盘空间,影响构建性能。
  4. 多模块项目需要合理设计

    • 模块划分合理:根据功能需求,将项目划分为独立的模块,避免模块之间过于紧密耦合。
    • 减少模块间的依赖循环:确保模块之间不出现循环依赖,通过层次化的模块结构,合理规划依赖关系。
  5. 及时更新与维护

    • 及时更新Maven和插件版本:定期更新Maven和插件到最新版本,获取新功能和性能改进。
    • 关注项目更新与变化:对于长期维护的项目,需要定期审查和更新项目的依赖和配置,确保项目的健康和安全。
  6. 使用Maven的有效实践

    • 遵循Maven的最佳实践:如遵循标准的目录结构、合理管理依赖范围、利用Maven的生命周期扩展功能等。
    • 利用IDE的Maven集成工具:现代IDE如Eclipse、IntelliJ IDEA等都对Maven提供了良好的集成支持,可以通过IDE的图形界面简化Maven项目的管理和构建。