type
status
date
slug
summary
tags
category
icon
password

一、Maven 是什么

在不借助项目管理工具的开发过程中我们通常会遇到这样的问题:
  • 在开发中,为了保证编译通过,我们会到处去寻找 jar 包,当编译通过了,运行的时候,却发现 "ClassNotFoundException" ,我们想到的是,难道还差 jar 包?例如在 spring 框架上开发的过程中我们至少要把 spring 的常用 jar 包和依赖包 common-logging 包下载下来,然后还要加入类路径和输出目录,工作显得非常累赘。
  • 每个 Java 项目的目录结构都没有一个统一的标准,配置文件到处都是,单元测试代码到底应该放在那里也没有一个权威的规范。
这时候就需要一个项目管理工具来对项目进行管理。Maven 是一个跨平台的项目管理工具,用于管理项目依赖,项目构建和项目生命周期的全过程。Maven 的作用包括:
  • 统一项目开发目录。例如所有的项目目录结构统一划分成 src/main/java (源代码目录)、src/main/resources (资源目录)、src/test/java (测试代码目录)、 src/test/resources (测试资源目录)、 target (生成文件目录)等目录。
  • 统一项目的生命周期,规范项目从开始构建到部署的建设过程。
  • 统一管理项目依赖,开发人员只需要定义所需要的依赖包,Maven 会自动搜索依赖包所依赖的其他包,不需要开发人员关心。
  • 测试和构建流程自动化和简单化。

二、Maven 安装和使用

安装Maven,可以从 Maven官网下载最新的 Maven 版本,然后在本地解压,设置几个环境变量:
  • Windows 把 %M2_HOME%\bin 添加到系统 Path 变量中。
  • MacOS 把上面内容添加到 ~/.bash_profile 文件,然后执行 source ~/.bash_profile 刷新环境变量。
执行下面命令,如果成功输出版本信息说明安装成功。

三、Maven 目录

参考 Maven 标准目录布局,Maven 项目是有规定的目录结构标准的,这样就很好解决了文件不知道放哪里、文件目录结构杂乱无章的问题。Maven 标准的目录如下
  • pom.xml:Maven 的核心配置文件
  • src/main/java:项目的源代码所在的目录
  • src/main/resources:项目的资源文件所在的目录
  • src/main/filters:项目的资源过滤文件所在的目录
  • src/main/webapp:如果是 web 项目,则该目录是 web 应用源代码所在的目录,比如 html 文件和 web.xml 等都在该目录下。
  • src/test/java:测试代码所在的目录
  • src/test/resources:测试相关的资源文件所在的目录
  • src/test/filters:测试相关的资源过滤文件所在的目录
下面这些目录平时用的不是很多
  • src/it:集成测试代码所在的目录,主要是供别的插件使用的。
  • src/assembly:组件(Assembly)描述符所在的目录
  • src/site:站点描述文件
  • LICENSE.txt:项目的许可文件
  • NOTICE.txt:该项目依赖的库的注意事项
  • README.txt:项目的readme文件
可以执行下面命令,创建一个最基本的 Maven 项目(命令的含义先不用管,后面会慢慢介绍)。
这个项目的目录结构如下所示:
至此我们已经创建了一个最简单的 Maven 项目。其中, src/main/java 目录包含 java 源码, src/test/java 目录包含 java 测试源码,而 pom.xml 文件是 maven 工程的配置文件。

四、Maven 基础

如果只是为了定义一个统一的项目目录结构,那上面这些流程实属有点大费周章。事实上统一的目录结构只是 Maven 的其中一部分内容,Maven 最关键的作用是用来管理整个项目的生命周期
我们先来明确以下 Maven 生命周期的几个概念。
  • 生命周期(Lifecycle)
  • 构建阶段(Phrase)
  • 目标(Goal)
  • 插件(Plugin)
举个例子,比如我们在项目中常执行的一些操作流程:
notion image
  • 这整一套流程可以为视作 Maven 项目的一个生命周期。
  • validatecompiletest 每一个都是一个构建阶段。每套生命周期对应一到多个构建阶段。运行命令执行某一个构建阶段,该阶段前面的所有阶段都会自动执行。
  • 目标代表一个特定的任务。一般写法是 xxx:xxx ,冒号前面是插件前缀,冒号后面是插件的目标。构建阶段和目标绑定,比如 complie 阶段绑定 compiler:compile 目标,test 阶段绑定 surefire:test 目标。一个构建阶段可以绑定零到多个目标,如果没有绑定目标就不会执行。不绑定到任何构建阶段的目标可以在构建生命周期之外通过直接调用执行。这些目标的执行顺序取决于调用目标和构建阶段的顺序。
  • 插件是真正去执行插件目标的工具。一个插件可以执行一到多个目标,比如 maven-compiler-plugin 插件可以执行 compiler:compilecompiler:testCompile 两个目标。
我们可以使用 Maven 命令来触发上面整个工作流程,比如下面命令:
我们来解读一下这个命令:
  • 这里的 cleanpakage 是构建阶段,dependency:copy-dependencies 是目标。
  • clean 阶段将会被首先执行,这里使用 Maven 插件 maven-clean-plugin 来执行目标 clean:clean 。如果找不到插件就会去远程仓库查找,下同。
  • 然后 dependency:copy-dependencies 目标会被执行,使用 Maven 插件 maven-dependency-plugin
  • 最终 package 阶段被执行,使用 Maven 插件 maven-jar-plugin 来执行目标 jar:jar
整个Maven 体系的知识点可以总结为下面几部分:
notion image
  • 仓库(Repository):通俗来说就是 jar 包的存放地址。仓库可以是本地的,也可以是远程的。当我们需要 jar 包的时候就去仓库里面拉取下来。
  • 依赖管理(Pom):通俗来说就是定义了项目需要哪些 jar 包,以及去哪个仓库拉取 jar 包。一般分为全局 Pom 文件和项目 Pom 文件:
    • 全局 Setting 文件定义了全局属性,所有 Maven 项目共享,比如 mirror 镜像、profile 多环境等。
    • 项目 Pom 文件定义了本 Maven 项目所需要的属性,比如 dependency 依赖、build 构建插件等。
  • 生命周期(Lifecycle):通俗来说就是定义了项目拉取 jar 包、编译运行、测试、打包成 jar 包、发布到仓库的整个流程。但生命周期不一定是固定的,有时候需要增加或者减少生命周期的某些阶段。为了提高灵活性,,Maven 把生命周期分成两个部分:
    • 构建阶段(Phrase):通俗来说就是定义了需要做哪些动作(Goal)。运行命令执行构建阶段的某个动作,该动作前面的所有动作都会自动执行。
    • 目标(Goal):通俗来说就是定义了动作的具体内容,比如打包、编译、测试这些具体动作。
    • 插件(Plugin):通过来说就是执行动作的工具。每一个动作(Goal)都由一个目标插件(Plugin)来负责执行,一个 Plugin 负责执行一到多个 Goal。
上面的概念可以使用下面的流程图来说明:
notion image
  1. 首先我们需要一个远程 Repository 仓库的地址,例如 Maven 官方的中央仓库。然后在全局的 Pom 文件里面定义好远程仓库的地址。(事实上我们还有一个本地仓库用来缓存远程仓库拉下来的 jar 包和插件,后面的文章会介绍)
  1. 在我们项目的 POM 文件里面定义好项目需要的依赖和插件。
  1. 刷新我们项目的 Maven 依赖,Maven 会自动从全局 Pom 文件定义的仓库地址拉取依赖(事实上这一步也是通过 Plugin 来完成的)。
  1. 我们的项目写完了,开始执行 Maven 项目的 Phrase 构建阶段。这一步会依次执行清理、编译、测试、打包和发布等步骤,每个步骤就是一个 Goal,每个 Goal 由一个 Plugin 插件来执行。我们输入 Maven 命令,比如 mvn clean ,插件 maven-clean-plugin 就会开始自动执行清理的动作。
  1. 构建阶段结束后,项目已经打包完成,然后发送到远程 Repository 仓库,至此我们 Maven 项目的一次生命周期流程结束。
Maven系列:Maven生命周期和插件Spring系列:使用SpEL表达式
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏