Maven 上手指南

Posted 河乐不为

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Maven 上手指南相关的知识,希望对你有一定的参考价值。

引言

最近开始学习 Spring Boot ,由于选用 Maven 作为构建工具,这也是 Java 后端开发常用的构建工具,当然也可以选用 Gradle ,Gradle 之前在 android 项目中使用居多,但近期也渐渐有取代 Maven 的趋势,后续可能会专门再写一篇关于 Gradle 的使用。这里先大致了解 Maven 管理项目的一些基础知识,这里主要参考官方的文档。

 

Maven简介

Maven 是一个项目管理和整合工具,为开发者提供了一套完整的构建生命周期框架。此工具简化和标准化了构建过程,有助于团队开发中完成如下工作:构建、文档、报告、依赖、scms、发布和分发等。

 

1. pom.xml

Maven 工程结构和内容通过一个 xml 文件来定义,即 pom.xml ,后续将详细说明此文件。

此外,由于 Maven 设计的理念 Conversion over configuration ,使用了约定大于配置的方式来定义构建过程,只要遵循默认的文件结构,在 pom.xml 中并不需要定义任何目录相关的配置。需要开发者定义的也只是生命周期目标和工程依赖,而且大部分工程管理和构建任务都是由 Maven 插件完成的。

 

2. Artifact(工具)

又或者可以将其成为模块,可以大致理解为一个项目最终生成的文件,可以是一个 jar/war 文件、源文件或二进制文件,甚至可以是一个 pom 文件。而每个 Artifact 都是通过 groudId:artifactId:version 作为标识来唯一确定的。假如希望一个 artifact 能够在其他项目中被使用,可以将其放到本地仓库中(通过 mvn install 实现);假如希望开放一个 artifact 给所有开发者使用,也可以将其提交到 Maven 的远程仓库中。

 

3. Repositories(仓库)

其实就是用来存储 artifact 的,分为本地仓库和远程仓库:

  • 本地仓库:是指个人电脑上的指定目录,默认是系统用户目录下的 .m2/repository 目录下,也可以通过 maven 安装目录下的 conf/setting.xml 中的标签来自定义;

  • 远程仓库:远程服务器上用来存储 artifact 的仓库,默认是指向 maven 的服务器仓库,也可以通过 maven 安装目录下的 conf/setting.xml 中的标签来指向其他源服务器。

项目中引用本地或远程仓库中 artifact 时,只需要在 pom.xml 中声明 dependency 即可,在编译代码时,maven 会自动根据依赖信息去下载对应的 artifact 。

 

4. build Lifecycles (构建生命周期)

Maven 设了标准的项目构建生命周期,分为三类

  • default LifeCycle

    处理项目的部署

  • clean LifeCycle

    处理项目的清理

  • site LifeCycle

    处理项目的文档生成

每一类生命周期,其实都包含了若干个 phase ,这里以 default LifeCycle 为例,其完整的 phase 如下:

<phases>
  <phase>validate</phase>
  <phase>initialize</phase>
  <phase>generate-sources</phase>
  <phase>process-sources</phase>
  <phase>generate-resources</phase>
  <phase>process-resources</phase>
  <phase>compile</phase>
  <phase>process-classes</phase>
  <phase>generate-test-sources</phase>
  <phase>process-test-sources</phase>
  <phase>generate-test-resources</phase>
  <phase>process-test-resources</phase>
  <phase>test-compile</phase>
  <phase>process-test-classes</phase>
  <phase>test</phase>
  <phase>prepare-package</phase>
  <phase>package</phase>
  <phase>pre-integration-test</phase>
  <phase>integration-test</phase>
  <phase>post-integration-test</phase>
  <phase>verify</phase>
  <phase>install</phase>
  <phase>deploy</phase>
</phases>

这些 phase 都是有序的,也就是每个 phase 必须等待前面的 phase 都执行完了才会执行。

当然,我们可以执行 mvn 命令来指定执行目标 phase (也称为 goal ,每个 phase 都可以作为 goal),即只执行至某个 phase ,例如我们后面会提及的工程编译命令 mvn compile ,其实就是指定执行目标 phase 为 compile ,而在这个过程会将此 phase 之前的 validate 、initialize 、generate-sources 、process-sources 、generate-resources 和 process-resources 这里个 phase 都执行了,再执行 compile ,而此 phase 之后的 phase 则不会被执行到。

default LifeCycle 中比较重要的 phase :

alidate #验证项目是否正确以及必须的信息是否可用
compile #编译源代码
test #测试编译后的代码,即执行单元测试代码
package #打包编译后的代码,在target目录下生成package文件
integration-test #处理package以便需要时可以部署到集成测试环境
verify #检验package是否有效并且达到质量标准
install #安装package到本地仓库,方便本地其它项目使用
deploy #部署,拷贝最终的package到远程仓库和替他开发这或项目共享,在集成或发布环境完成

Maven 中的构建生命周期其实也是 Maven 最为人诟病的地方,因为把周期限制死了,无法根据实际情况添加新的 phase ,而只能将插件绑定到已有的 phase 上。

 

安装和配置

1. 安装配置

在 Windows 系统下安装配置 Maven 其实很简单,直接在官网下载安装包,解压缩到本地,再将其 bin 目录绝对路径配置到系统环境变量 PATH 中即可。步骤如下:

  • 下载最新的压缩包,例如:apache-maven-3.6.0-bin.zip

  • 解压然后将解压后的 bin 目录配置到系统环境变量;

  • 在命令行输入 mvn -v / mvn --version 测试是否安装成功,假如操作无误,则会输出如下:

    Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T02:41:47+08:00)
    Maven home: E:\\Java\\Installs\\apache-maven-3.6.0\\bin\\..
    Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: D:\\Android\\JDK1.8\\jre
    Default locale: zh_CN, platform encoding: GBK
    OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

 

2. 本地仓库配置

上述是 Maven 安装的相关配置,此外,Maven 远端仓库其实提供了很多可用的模块,而假如需要在本地项目中使用,在编译项目时 maven 会自动将用到的模块都下载到本地仓库中,因此需要配置本地仓库的地址,配置通过在 maven 安装目录中 conf/setting.xml 中的配置项实现,例如:

<localRepository>E:\\Java\\Workplace\\Maven\\repo</localRepository>

此时,便将 maven 本地仓库地址指定为 E:\\Java\\Workplace\\Maven\\repo

 

3. 远程仓库配置

由于远端仓库服务器在国外,国内访问时常常会出现超时和下载失败的情况,可以通过指定源地址为国内的方式来解决,也是在 setting.xml 的 <mirrors> 节点中添加如下内容:

<mirror>
    <id>alimaven</id>
    <mirrorOf>central</mirrorOf>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>

如此,便把远端仓库地址由默认改为阿里云的源。

 

pom.xml 管理文件

项目对象模型和 POM 是 Maven 的基本工作单元, pom.xml 文件包含了 Maven 构建工程时所需的工程和配置信息,也包含了大多数工程构建的默认配置信息,是使用 Maven 来管理的项目必不可少的文件。

查看 POM 官方文档 ,而标签的各种具体使用说明,也可查看 Guide to Configuring Plug-ins

 

Maven 基本命令

作为一个项目管理工具,我们至少需要了解如何创建、构建和打包工程。

1. 创建工程

Maven 使用原型(archetype)插件来创建工程,此插件实际上是从现有的 Maven 模板列表中挑选出一个作为原型,从而生成项目,接下来我们尝试生成一个 demo 工程,在命令行输入如下命令:

$ mvn archetype:generate 
-DgroupId=com.linsh.test #工程包名
-DartifactId=mvn_demo #工程名称
-DarchetypeArtifactId=maven-archetype-quickstart 
-DarchetypeVersion=1.4 
-DinteractiveMode=false

这里几个参数的意义大致是:

  • DgroupId 工程的 groudId ,DartifactId 工程的 artifactId ,与后面的 DarchetypeVersion 三个参数结合起来在 Maven 仓库中作为模块的唯一标示;

  • DarchetypeArtifactId 是用于创建项目的原型模板的 artifactId ,这里我们选择的 maven-archetype-quickstart 适用于创建 Java 项目,假如要创建一个 Java Web 的项目,只需选择 maven-archetype-webapp 模板即可;

  • DarchetypeVersion 是模板的版本(有时也可以忽略,默认使用最新的版本);

  • DinteractiveMode 是否使用交互模式(由用户填写版本信息等,不使用则采用默认值)。

假如创建成功则可以看到如下输出:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: packageInPathFormat, Value: com/linsh/test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.linsh.test
[INFO] Parameter: groupId, Value: com.linsh.test
[INFO] Parameter: artifactId, Value: mvn_demo
[INFO] Project created from Archetype in dir: E:\\Java\\Workplace\\projects\\TestMaven\\mvn_demo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.258 s
[INFO] Finished at: 2019-01-17T10:40:05+08:00
[INFO] ------------------------------------------------------------------------

此时,在命令行当前所在目录下,会创建一个名称为 mvn_demo(与设置的 artifactId 参数值对应)的工程目录。

 

2. 编译工程

$ mvn compile # 或者 mvn compiler:compile

执行此命令后,工程中 src/main 目录下的 Java 源码会编程生成对应的 .class 文件到目录 target/classes 之下,假如想要编译 src/test 下的源码,可以使用如下命令:

$ mvn test-compile # 或者 mvn compiler:testCompile

编译结果放在 target/test-classes 目录下。

从 3.0 版本开始,maven 默认的编译器就是 javax.tools.JavaCompiler ,用于编译 Java 源码,假如想使用 javac 来编译,可以在编译命令中设置参数 forceJavacCompilerUse

$ mvn compile -Dmaven.compiler.forceJavacCompilerUse=true

除此之外,maven 目前还支持其他的编译器,例如:AspectJ.NETC#

 

3. 清理缓存

$ mvn clean

用于清理编译和打包生成的缓存文件,其实就是把 target 目录删除掉。通常在执行打包命令之前会先调用此命令清理缓存文件,从而保证打出的包是最新的。

有时候,假如需要在每次构建工程的时候自动执行一次 clean 命令,且无需设置清理参数,可以直接在 pom.xml 中的 <artifactId>maven-clean-plugin</artifactId> 标签之后添加自动清理设置,如下:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>auto-clean</id>
            <phase>initialize</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

如此,在工程每次构建的 initialize 阶段就会先自动执行清理命令。

 

4. 打包工程

$ mvn package

为了保险起见,通常在打包前先清理之前的缓存文件,所以打包命令通常如下:

$ mvn clean package

打包正常输出如下:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.linsh.test:mvn_demo >-----------------------
[INFO] Building mvn_demo 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ mvn_demo ---
[INFO] Deleting E:\\Java\\Workplace\\projects\\mvn_demo\\target
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\\Java\\Workplace\\projects\\mvn_demo\\src\\main\\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\\Java\\Workplace\\projects\\mvn_demo\\target\\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ mvn_demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory E:\\Java\\Workplace\\projects\\mvn_demo\\src\\test\\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ mvn_demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to E:\\Java\\Workplace\\projects\\mvn_demo\\target\\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ mvn_demo ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.linsh.test.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in com.linsh.test.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ mvn_demo ---
[INFO] Building jar: E:\\Java\\Workplace\\projects\\mvn_demo\\target\\mvn_demo-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.052 s
[INFO] Finished at: 2019-01-19T12:39:53+08:00
[INFO] ------------------------------------------------------------------------

打包过程中完成的事情:

  • target 目录清理掉;

  • 编译工程中src 中的 main 目录下的工程源码和 test 目录下的测试源码;

  • 运行测试用例,并生成对应的测试报告到 target/surefire-reports 目录下;

  • 构建工程生成 jar 文件, jar 文件的命名规则是:(artifactId)-(version).jar 例如本工程生成的 mvn_demo-1.0-SNAPSHOT.jar ,而这两项参数其实都可以在 pom.xml 中进行修改。

其他

1. 常用命令

除了上述三个核心的命令之外,还有一些其他的常用命令,大致介绍如下:

  • mvn install :将当前工程作为模块安装到本地的 Maven 仓库中,如此便可在其他工程中以模块的方式引入此工程;

  • mvn site :生成项目相关信息的文档

此外,mvn 命令除了指定 goal 外,还能添加一些参数项来排查问题,常用的参数有:

  • -e 显示详细错误

  • -U 强制更新 snapshot 类型的插件或依赖库(否则maven一天只会更新一次snapshot依赖)

  • -o 运行 offline 模式,不联网更新依赖

  • -N 仅在当前项目模块执行命令,关闭 reactor

  • -pl module_name 在指定模块上执行命令

  • -ff 在递归执行命令过程中,一旦发生错误就直接退出

  • -Dxxx=yyy 指定java全局属性

  • -Pxxx 引用profile xxx

 

2. Junit 测试框架

看了 demo 工程不难发现,在 pom.xml 引入了 junit ,这其实是一个回归测试框架(只适用于 Java 工程),被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量。其实,查看 AppTest.java 中的源码,就会发现测试用例就是使用此框架来对应用进行单元测试的。

当然,这个框架其实是开源的,如今最新的版本 5.0 ,但正式版本还是 4.x ,此 demo 中使用的就是 4.11 版本。 Github 源码地址:junit4

 

3. 搜索 Maven 模块

假如想要查找和浏览远端中央仓库中可用的模块,可以通过此地址:The Central Repositorymvnrepository

 

参考

 


微信公众号「何乐不为呢」,一个码农的技术笔记和唠叨。

以上是关于Maven 上手指南的主要内容,如果未能解决你的问题,请参考以下文章

IDEA使用git对HitHub管理(零基础上手Git)

有了Gradle,还会选Maven吗?

Maven环境隔离

Maven入门指南 Maven 快速入门及简单使用

《Maven权威指南》读书笔记

Intellij IDEA 2021 Maven 配置指南