Maven 从菜鸟到大神,简易教程

一、Maven概述

Maven 是什么?

Maven 是一个项目管理和整合工具。Maven 为开发者提供了一套完整的构建生命周期框架。开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置,因为 Maven 使用了一个标准的目录结构和一个默认的构建生命周期。

在有多个开发团队环境的情况下,Maven 能够在很短的时间内使得每项工作都按照标准进行。因为大部分的工程配置操作都非常简单并且可复用,在创建报告、检查、构建和测试自动配置时,Maven 可以让开发者的工作变得更简单。

Maven 能够帮助开发者完成以下工作:

  • 构建
  • 文档生成
  • 报告
  • 依赖
  • SCMs
  • 发布
  • 分发
  • 邮件列表

Maven 的目标

Maven 的主要目的是为开发者提供

  • 一个可复用、可维护、更易理解的工程综合模型
  • 与这个模型交互的插件或者工具

Maven 工程结构和内容被定义在一个 xml 文件中 - pom.xml,是 Project Object Model (POM) 的简称,此文件是整个 Maven 系统的基础组件。

约定优于配置

开发者不需要再关心每一个配置细节,比如说,代码存放在哪里,打包的class在哪里,等等。Maven 为工程提供了合理的默认行为。当创建 Maven 工程时,Maven 会创建默认的工程结构。开发者只需要合理的放置文件

举例说明,下面的表格展示了工程源码文件、资源文件的默认配置,和其他一些配置。假定 ${basedir} 表示工程目录:

配置项 默认值
source code ${basedir}/src/main/java
resources ${basedir}/src/main/resources
Tests ${basedir}/src/test
Complied byte code ${basedir}/target
distributable JAR ${basedir}/target/classes

为了构建工程,Maven 为开发者提供了选项来配置生命周期目标和工程依赖(依赖于 Maven 的插件扩展功能和默认的约定)。大部分的工程管理和构建任务是由 Maven 插件完成的。

开发人员不需要了解每个插件是如何工作的,就能够构建任何Maven 工程。使用插件只需要进行简单的配置,就可以使用

二、POM

POM 它放在工程根目录下,包含了关于工程和各种配置细节的信息,Maven 使用这些信息构建工程。

POM 也包含了目标和插件。当执行一个任务或者目标时,Maven 会查找当前目录下的 POM,从其中读取所需要的配置信息,然后执行目标。

POM 常用的配置,下面会进行详细介绍。

POM必须的字段

  • 每个工程应该只有一个 POM 文件。

  • 所有的 POM 文件需要 project 元素和三个必须的字段:groupId, artifactId,version。表达当前工程的信息

  • 在仓库中的工程标识为 groupId:artifactId:version
节点 描述
groupId 这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.company.bank 拥有所有的和银行相关的项目。
artifactId 这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置。
version 这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本。例如:com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1.

Super POM

所有的 POM 都继承自一个父 POM(无论是否显式定义了这个父 POM)。父 POM 也被称作 Super POM,它包含了一些可以被继承的默认设置。

Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被方便的重写。

三、Maven - 构建生命周期

要了解构建生命周期,需要认识这三个字段 :

  1. lifecycle 生命周期
  2. phase 阶段
  3. goal 目标

lifecycle 中包含phase ,phase 中包含goal 。

mvn命令后面可以跟随phase 或goal。执行命令时,其实就是执行的phase 中的goal 。goal 也可以单独执行。
例如mvn clean 命令后面的clean,是一个phase ,它执行的就是clean lifecycle中的 clean phase中的clean goal 。

下面对这三个字段进行详细的介绍:

3.1、lifecycle

每个lifecycle 中都包含一个或多个phase 。

通过 Maven 命令调用lifecycle中的phase时,该lifecycle中phase之前以及包括该phase在内的所有phase会被执行。

Maven 有以下三个默认的生命周期:

  • clean
  • default(or build)
  • site

下面介绍这三个生命周期

3.1.1、Clean 生命周期

Maven 调用 clean 生命周期,它包含以下phase 。

  • pre-clean
  • clean
  • post-clean

Maven 的 clean goal (clean:clean)绑定到了 clean lifecycle的 clean phase 。它的 clean:clean 目标通过删除构建目录删除了构建输出。所以当 mvn clean 命令执行时,Maven 删除了构建目录。

3.1.2、Default (or Build) 生命周期

Maven 的主要生命周期,被用于构建应用。包括下面的 23 个阶段。

phase 描述
validate 检查工程配置是否正确,完成构建过程的所有必要信息是否能够获取到。
initialize 初始化构建状态,例如设置属性。
generate-sources 生成编译阶段需要包含的任何源码文件。
process-sources 处理源代码,例如,过滤任何值(filter any value)。
generate-resources 生成工程包中需要包含的资源文件。
process-resources 拷贝和处理资源文件到目的目录中,为打包阶段做准备。
compile 编译工程源码。
process-classes 处理编译生成的文件,例如 Java Class 字节码的加强和优化。
generate-test-sources 生成编译阶段需要包含的任何测试源代码。
process-test-sources 处理测试源代码,例如,过滤任何值(filter any values)。
test-compile 编译测试源代码到测试目的目录。
process-test-classes 处理测试代码文件编译后生成的文件。
test 使用适当的单元测试框架(例如JUnit)运行测试。
prepare-package 在真正打包之前,为准备打包执行任何必要的操作。
package 获取编译后的代码,并按照可发布的格式进行打包,例如 JAR、WAR 或者 EAR 文件。
pre-integration-test 在集成测试执行之前,执行所需的操作。例如,设置所需的环境变量。
integration-test 处理和部署必须的工程包到集成测试能够运行的环境中。
post-integration-test 在集成测试被执行后执行必要的操作。例如,清理环境。
verify 运行检查操作来验证工程包是有效的,并满足质量要求。
install 安装工程包到本地仓库中,该仓库可以作为本地其他工程的依赖。
deploy 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。

通过 Maven 命令调用phase时,例如 mvn compile,该phase之前以及包括该phase在内的所有phase会被执行。

3.1.3、Site 生命周期

Maven Site 插件一般用来创建新的报告文档、部署站点等。

这个生命周期包括的阶段:

  • pre-site
  • site
  • post-site
  • site-deploy

3.2、phase

执行phase实际执行的是goal。如果一个phase没有绑定goal,这个phase就不会被执行。

每个phase定义了一个或多个goals ,其中的goals是顺序执行。

一些phase默认已经绑定了一些goal。对于default lifecycle来说, 这些被绑定的goal并不完全相同,而是和packaging value相关。

所谓的packaging value就是< packaging>jar< / packaging>,对于不同的包类型,打包的过程不尽相同,因此需要执行的goal也不同。

3.3.goal

最终被执行的就是goal

goal与goal之间是独立的。因此单独执行一个goal不会导致其他goal被执行。

3.4、举个例子

mvn clean dependency:copy-dependencies package
  • clean是phase。

  • dependency:copy-dependencies是plugin-in dependency 中的 copy-dependencies 目标。(这里涉及到插件,后面会讲到)

  • package也是一个phase。

maven会顺序执行这3个对象中包含的所有goal。

四、Maven - 仓库

在 Maven 的术语中,仓库是一个位置(place),就是项目中依赖的第三方库,这个库所在的位置叫做仓库。
Maven 仓库有三种类型:

  • 本地(local)
  • 中央(central)
  • 远程(remote)

4.1、本地仓库

Maven 本地仓库是机器上的一个文件夹。它在你第一次运行任何 maven 命令的时候创建。

Maven 本地仓库保存你的工程的所有依赖(library jar、plugin jar 等)。当你运行一次 Maven 构建,Maven 会自动从中央库或远程库下载所有依赖的 jar 文件到本地仓库中。它避免了每次构建时都引用存放在远程机器上的依赖文件。

Maven 本地仓库默认被创建在 %USER_HOME% 目录下。要修改默认位置,在 %M2_HOME%\conf 目录中的 Maven 的 settings.xml 文件中定义另一个路径。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 
   http://maven.apache.org/xsd/settings-1.0.0.xsd">
      <localRepository>C:/MyLocalRepository</localRepository>
</settings>

当你运行 Maven 命令,Maven 将下载依赖的文件到你指定的路径中。

4.2、中央仓库

Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。通俗一点说,就是一个网站,上面存放大量的库,项目中用到中央仓库的相关文件,就自动下载下来

中央仓库的关键概念:

  • 这个仓库由 Maven 社区管理。
  • 不需要配置。
  • 需要通过网络才能访问。

要浏览中央仓库的内容,maven 社区提供了一个 URL:http://search.maven.org/#browse。使用这个仓库,开发人员可以搜索所有可以获取的代码库。

4.3、远程仓库

如果 Maven 在中央仓库中也找不到依赖的库文件,它会停止构建过程并输出错误信息到控制台。

开发人员可以自己定制仓库,包含所需要文件。这样的仓库叫做远程仓库

举例说明,使用下面的 POM.xml,Maven 将从远程仓库中下载该 pom.xml 中声明的所依赖的(在中央仓库中获取不到的)文件:

<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.companyname.projectgroup</groupId>
   <artifactId>project</artifactId>
   <version>1.0</version>
   <dependencies>
      <dependency>
         <groupId>com.companyname.common-lib</groupId>
         <artifactId>common-lib</artifactId>
         <version>1.0.0</version>
      </dependency>
   <dependencies>
   <repositories>
      <repository>
         <id>companyname.lib1</id>
         <url>http://download.companyname.org/maven2/lib1</url>
      </repository>
      <repository>
         <id>companyname.lib2</id>
         <url>http://download.companyname.org/maven2/lib2</url>
      </repository>
   </repositories>
</project>

4.4、Maven 依赖搜索顺序

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库:

步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中。
步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库已被将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)

五、Maven - plugin

另外一种将goal绑定到phase的方法就是在project中使用plugin,一个plugin可能有一个或多个goal,其中每个goal代表一个plugin的功能。

Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成。Maven 插件通常被用来:

  • 创建 jar 文件
  • 创建 war 文件
  • 编译代码文件
  • 代码单元测试
  • 创建工程文档
  • 创建工程报告

5.1、插件的使用

一、插件通常提供了一个目标的集合,并且可以使用下面的语法执行:

mvn [plugin-name]:[goal-name]

例如,一个 Java 工程可以使用 maven-compiler plugin 的 compile (goal) 编译,使用以下命令:

mvn compiler:compile

二、把plugin绑定到phase上,执行这个phase时,就会执行对于的插件了

5.2、举个例子

maven中所有的插件都是配置在标签 <build>–><plugins>下面,其下每一个<plugin>标签对应一个插件。

官方自带的插件五花八门,用的最多的是maven-compiler-plugin、maven-dependency-plugin、maven-surefire-plugin等。官方网址

每一个插件可以定义插件的groupId与artifactId,以及要执行的<executions>。

executions下可以定义一大堆的execution用来定义具体的任务,其中又包括目标、绑定的阶段、配置等参数。大致上配置文件如下:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <source>1.7</source>
                            <target>1.7</target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.10</version>
                <executions>
                    <execution>
                        <id>get_source</id>
                        <goals>
                            <goal>get</goal>
                            <goal>unpack</goal>
                        </goals>
                        <phase>process-resources</phase>
                        <configuration>
                            <artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>com.alibaba.middleware.race</groupId>
                                    <artifactId>rpc-api</artifactId>
                                    <version>1.0</version>
                                    <classifier>sources</classifier>
                                </artifactItem>
                            </artifactItems>
                            <outputDirectory>${project.build.sourceDirectory}</outputDirectory>
                            <excludes>META-INF\/**</excludes>
                        </configuration>
                    </execution>
                </executions>

                <!--<configuration>-->
                    <!--<artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact>-->
                <!--</configuration>-->
            </plugin>
        </plugins>
    </build>
  • 其中maven-dependency-plugin插件下的任务先从中央库下载com.alibaba.middleware.race:rpc-api:1.0:jar:sources的jar包,
  • 解压jar包到指定的目录并排除META-INF文件夹。(由于本人刚接触,这种写法可能不是最佳实践,如果有人有更好的写法的话恳请告知。)
  • 这个id为get_source的任务绑定到了process-resources phase,在执行到default生命周期的该阶段时会执行这个任务。运行mvn compile,成功执行,感觉良好。

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

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

六、Maven - 构建自动化

构建自动化定义为一种场景:一旦该工程成功构建完成,其相关的依赖工程即开始构建,目的是为了保证其依赖项目的稳定。

实例
考虑一个团队正在开发一个关于总线核心 Api(称其为 bus-core-api)的工程,依赖它的工程有 2 个,分别为网页 UI(称其为 app-web-ui)和应用程序桌面 UI(称其为 app-desktop-ui)。

app-web-ui 工程使用 1.0-SNAPSHOT 总线核心 Api 工程,其 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>app-web-ui</groupId>
   <artifactId>app-web-ui</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <dependencies>
      <dependency>
      <groupId>bus-core-api</groupId>
         <artifactId>bus-core-api</artifactId>
         <version>1.0-SNAPSHOT</version>
      </dependency>
   </dependencies>
</project>

app-desktop-ui 工程也正在使用 1.0-SNAPSHOT 总线核心 Api 工程,其 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>app-desktop-ui</groupId>
   <artifactId>app-desktop-ui</artifactId>
   <version>1.0</version>
   <packaging>jar</packaging>
   <dependencies>
      <dependency>
      <groupId>bus-core-api</groupId>
         <artifactId>bus-core-api</artifactId>
         <version>1.0-SNAPSHOT</version>
      </dependency>
   </dependencies>
</project>

bus-core-api 工程的 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>bus-core-api</groupId>
   <artifactId>bus-core-api</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>   
</project>

现在,如果bus-core-api 工程有变化时, 如何保证 app-web-ui 和 app-desktop-ui 工程随时被构建?

使用快照可以保证最新的 bus-core-api 工程可以被使用,但是为了达到上述的需求,我们仍需做一些额外的工作。

我们有 2 种方式:

  1. 在 bus-core-api 的 pom 文件里添加一个编译目标来提醒 app-web-ui 工程和 app-desktop-ui 工程启动创建。
  2. 使用一个持续集成(CI)的服务器,比如 Hudson,来实现自动化创建。

下面只介绍第一种方法:

使用 Maven
更新 bus-core-api 工程的 pom.xml 文件

<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>bus-core-api</groupId>
   <artifactId>bus-core-api</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <build>
   <plugins>
   <plugin>
   <artifactId>maven-invoker-plugin</artifactId>
   <version>1.6</version>
      <configuration>
         <debug>true</debug>
         <pomIncludes>
            <pomInclude>app-web-ui/pom.xml</pomInclude>
            <pomInclude>app-desktop-ui/pom.xml</pomInclude> 
         </pomIncludes>
      </configuration>
      <executions>
         <execution>
            <id>build</id>
            <goals>
               <goal>run</goal>
            </goals>
         </execution>
      </executions>
   </plugin>
   </plugins>
   <build>
</project>

打开命令终端,进入到 C:\ > MVN > bus-core-api 的目录下,然后执行如下的 mvn 的命令。

C:\MVN\bus-core-api>mvn clean package -U

Maven 将会开始构建 bus-core-api 工程,输出日志如下:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------
[INFO] Building bus-core-api
[INFO]    task-segment: [clean, package]
[INFO] ------------------------------------------------------------------
...
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: C:\MVN\bus-core-ui\target\
bus-core-ui-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------

一旦 bus-core-api 构建成功,Maven 将会自动开始构建 app-web-ui 项目, 日志如下:

[INFO] ------------------------------------------------------------------
[INFO] Building app-web-ui 
[INFO]    task-segment: [package]
[INFO] ------------------------------------------------------------------
...
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: C:\MVN\app-web-ui\target\
app-web-ui-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------

等到 app-web-ui 创建成功,Maven 接着开始构建 app-desktop-ui 工程,日志输出如下:

[INFO] ------------------------------------------------------------------
[INFO] Building app-desktop-ui 
[INFO]    task-segment: [package]
[INFO] ------------------------------------------------------------------
...
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: C:\MVN\app-desktop-ui\target\
app-desktop-ui-1.0-SNAPSHOT.jar
[INFO] -------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] -------------------------------------------------------------------

七、一些maven标签

1、dependencies与dependencyManagement的区别

2、properties标签定义变量

3、使用import scope解决maven继承(单)问题

4、maven的pom.xml中标签的详细说明


这篇文章的大纲是参考Maven - 概述,我觉得不常用的知识就没有写出来,你也可以去看看,不过翻译的很烂,有的文章写得不好,建议先从那里知道有哪些知识点,再去搜索这些知识点具体怎么用

参考:
Maven中的几个重要概念(二):lifecycle, phase and goal
Maven - 概述
Maven的插件:命令行执行
Maven plugin中的lifecycle、phase、goal、mojo概念及作用的理解
maven configuration
深入理解maven及应用–转

关注我的公众号,轻松了解和学习更多技术
这里写图片描述

展开阅读全文
©️2020 CSDN 皮肤主题: 撸撸猫 设计师: 设计师小姐姐 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值