Maven的安装和使用

1 前言

Maven是一个比Ant更先进的项目管理工具,它采用一种“约定优于配置(CoC)”的策略来管理项目。它不仅用于把源代码构建成可发布的项目(包括编译、打包、测试和分发),还可以生成报告、生成Web站点等。

2 下载和安装Maven

下载和安装Maven按如下步骤进行:

Step 1:登录Maven站点下载Maven最新版。虽然Maven是基于Java的生成工具,具有平台无关的特性,但考虑到解压缩的方便性,通常建议Windows平台下载*.zip压缩包,而Linux平台下载.gz压缩包。

Step 2:将下载的压缩文件解压缩到任意路径,解压缩后看到如下文件结构:

  • bin:保存Maven的可执行命令。其中mvnmvn.bat就是执行Maven工具的命令。
  • boot:该目录只包含一个plexus-classworlds-2.6.0.jarplexus-classworlds是一个类加载器框架,与默认的Java类加载器相比,它提供了更丰富的语法以方便配置,Maven使用该框架加载自己的类库。通常无需理会。
  • conf:保存Maven配置文件的目录,该目录包含settings.xml文件,该文件用于设置Maven的全局行为。通常建议将该文件复制到~/.m2/目录下(~表示用户目录),这样可以只设置当前用户的Maven行为。
  • lib:该目录包含了所有Maven运行时需要的类库,Maven本身是分模块开发的,因此用户能看到诸如maven-core-3.6.3.jarmaven-repository-metadata-3.6.3.jar等文件。此外,还包含Maven所依赖的第三方类库。
  • LICENSE、README.txt等说明文档。

Step 3:Maven的运行需要如下两个环境变量:

  • JAVA_HOME:该环境变量应指向JDK安装路径。如果已经成功安装了Tomcat,则环境变量应该是已经正确的
  • M2_HOME:该环境变量应指向Maven安装路径。

提示:Maven安装路径就是前面释放Maven压缩文件的路径。Maven安装路径下应该包含bin、boot、conf和lib4个文件夹。

Step 4:Maven工具的关键命令就是%M2_HOME%/bin路径下的mvn.bat命令,如果希望操作系统可以识别该命令,还应该将%M2_HOME%/bin路径添加到操作系统的PATH环境变量之中。

Step 5(可选):在%M2_HOME%/conf/settings.xml中添加如下代码,因为使用Maven过程中涉及很多插件的下载,而这些插件都是在国外Maven的中央仓库,下载会很缓慢,所以添加国内的镜像的话下载速度会起飞哦!

1
2
3
4
5
6
7
8
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>

经过上面5个步骤,Maven安装成功,启动命令行窗口,输入如下命令(如果未将%M2_HOME%/bin路径添加到操作系统的PATH环境变量之中,则输入mvn.bat的全路径):

1
mvn help:system

通过该命令应该先看到Maven不断地从网络下载各种文件,然后会显示如下两类信息:

  • System Properties
  • Environment Variables

如果能看到Maven输出如上两类信息,则表明Maven安装成功。

3 设置Maven

设置Maven行为有两种方式

  • 全局方式:通过Maven安装目录下的conf/settings.xml文件进行设置
  • 当前用户方式:通过用户Home目录C:\Users\用户名\m2\目录下的settings.xml文件进行设置

上面两种方式只是起作用的范围不同,但它们都是用settings.xml作为配置文件,而且两种方式中settings.xml文件允许定义的元素也是相同的。

通常来说,Maven允许设置如下参数:

  • localRepository:该参数通过<localRepository.../>元素设置,该元素的内容是一个路径字符串,该路径用于设置Maven的本地资源库的路径。如果用户不设置该参数,Maven本地资源库默认保存在用户Home目录的m2/repository路径下。Windows系统建议将该Maven本机资源库设置到其他路径。

提示:资源库是Maven的一个重要概念,Maven构建项目所使用的插件、第三方依赖库都集中存放在本地资源库中。

  • interactiveMode:该参数通过<interactiveMode.../>元素设置,该参数设置Maven是否处于交互模式——如果将Maven设为交互模式,每当Maven需要用户输入时,Maven都会提示用户输入。但如果将该参数设置为false,那么Maven将不会提示用户输入,而是“智能”地使用默认值。
  • offline:该参数设置Maven是否处于离线状态,如果将该参数设为false,每当Maven找不到插件、依赖库时,Maven总会尝试从网络下载
  • proxies:该参数用于为Maven设置代理服务器。该参数可包含多个<proxy.../>,每个<proxy.../>设置一个代理服务器,包括代理服务器地ID、协议、代理服务器地址、代理服务器端口、用户名、密码等信息,Maven可通过代理服务器访问网络

如果网络通常,通常只需通过localReposity设置Maven的本地资源库路径,接下来即可正常使用Maven工具了。

前面已经提到,Maven工具的命令主要就是mvn,该命令的基本格式是:

1
mvn <plugin-prefix>:<goal> -D<属性名>=<属性值> ...

上面mvn命令中,plugin-prefix是一个有效的插件前缀,goal就是该插件所包含的制定目标,-D用于为该目标指定属性,每次运行mvn命令可通过多个-D选项来指定属性名、属性值

提示:除了使用plugin-prefix的形式来代表指定插件之外,还可使用如下命令来运行指定插件:

1
mvn <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>:<goal>

其中plugin-group-idplugin-artifact-idplugin-version被称为Maven坐标,可用于唯一地表示某个项目

对于前面验证Maven是否安装成功所用的命令:mvn help:system,其中help就是一个典型的Maven插件,system就是help插件的goal

提示:Maven插件是一个非常重要的概念,从某种程度来看,Maven核心是一个空的“容器”。Maven核心其实并不做什么实际的事情,它只是解析一些XML文档,管理生命周期和插件,除此之外,Maven什么也不懂。Maven的强大来自于它的插件,这些插件可以编译源代码、打包二进制代码、发布站点等。换句话说,Maven的“空”才是它的强大,因为Maven是“空”的,所以它可以装各种插件,因此它的功能可以无限扩展。直接从Apache下载的Maven不知道如何编译Java代码,不知道如何打包WAR文件,也不知道如何运行单元测试….它什么都不懂。当开发者第一次使用全新的Maven运行诸如mvn install命令时,Maven会自动从远程资源库下载大部分核心Maven插件。

4 创建、构建简单的项目

创建项目使用Maven的archetype插件,关于Maven插件的功能和用法可登录http://maven.apache.org/plugins/index.html页面进行查看,该页面显示了各种Maven插件的列表。

其中显示了创建项目需要使用的archetype插件,单击该链接即可打开archetype插件使用说明

从图中可以看出,Maven的archetype插件包含如下目标(goal)

  • archetype:generate:使用指定原型创建一个Maven项目
  • archetype:create-from-project:使用已有的项目创建Maven项目
  • archetype:crawl:从仓库中搜索原型

从上面介绍可以看出,使用mvn archetype:generate命令即可创建Maven项目,使用该命令还需要指定一些参数(通过-D选项指定),单击”archetype:generate”链接即可看到如图所示的参数页面。

上面介绍的过程就是通过官方站点查看Maven插件的过程,由于Maven支持的插件非常多,而且每个插件有可能包含多个目标,所以应该掌握Maven插件的技巧。

掌握archetype插件的用法之后,即可使用如下命令来创建简单的Java项目:

1
mvn archetype:generate -DinteractiveMode=false -DgroupId=org.fkjava -DartifactId=mavenQs -Dpackage=org.fkjava.mavenqs

如果用户第一次执行该命令,将看到Maven不断地从网络下载各种文件的信息,这是Maven正从网络下载archetype插件的各种相关文件。

提示:实际运行该命令时,可能运行失败——只要网络状态不好,就可能无法正常从网络下载archetype插件的各种相关文件,上面命令就会下载失败,第一次执行Maven的某个插件时往往很容易失败,可以多尝试几次。

上面命令执行完成后,会生成一个mavenQs文件夹,该文件夹的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mavenQs
├─pom.xml
└─src
├─main
│ └─java
│ └─org
│ └─fkjava
│ └─mavenqs
| └─App.java
└─test
└─java
└─org
└─fkjava
└─mavenqs
└─AppTest.java

上面项目中的App.java是archetype插件生成的一个简单的Java类,而AppTest则是该插件App生成的测试用力

除此之外,还可以看到该项目的根路径下包含一个pom.xml文件,该文件的作用类似于Ant的build.xml文件,但它的内容比build.xml文件的内容简洁得多

打开pom.xml文件可以看到如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fkjava</groupId>
<artifactId>mavenQs</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>mavenQs</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

pom.xml文件被称为项目对象模型(Project Object Model)描述文件,Maven使用一种被称为项目对象模型的方式来管理项目,POM用于描述如下问题:该项目是什么类型的?该项目的名称是什么?该项目的构建能自定义吗?Maven使用pom.xml文件来描述项目对象模型。因此,pom.xml并不是简单的生成文件,而是一种项目对象模型的描述文件。

上面所看到的pom.xml文件将是Maven项目中最简单的。一般来说,实际pom.xml文件将比这个文件更复杂:它会定义多个依赖,定义额外的插件等。上面pom.xml中的<groupId.../><artifactId.../><packaging.../><version.../>定义了该项目的唯一标识(几乎所有的pom.xml文件都需要定义他们),这个唯一标识被称为Maven坐标(coordinate)。<name.../><url.../>元素只是pom.xml提供的描述性元素,用于提供可阅读的名字。

上面的pom.xml文件还包含了一个<dependencies.../>元素,该元素定义了一个单独的测试范围的依赖,这表明该项目的测试依赖于JUnit测试框架。

从上面代码可以看出,pom.xml文件仅仅包含了该项目的版本、groupId、artifactId等坐标信息。并未指定任何编译Java程序、打包、运行Java程序的详细命令。那么这份文件是否能编译、打包项目呢?

在pom.xml所在路径下输入命令:

1
mvn compile

上面命令使用mvn运行compile插件的默认目标。如果用户第一次执行该命令,将可以看到Maven不断从网络下载各种文件的信息,这是Maven正从网络下载compile插件的各种相关文件。

如果网络状态没有问题,Maven将会先下载compile插件,额案后即可成功执行compie插件,这样将会正常编译该项目。

注意:如果执行compile时出现以下报错,则在pom.xml文件中增加maven编译的jdk版本设置,maven.compiler.source和maven.compiler.target,另外java.version最好也加上。我的jdk版本是jdk-13.0.2,所以写13。

1
2
3
4
5
6
7
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>13</java.version>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
</properties>

项目编译完成后,接下来可以使用Maven的exec插件来执行Java类。使用Maven执行Java程序的命令如下:

1
mvn exec:java -Dexec.mainClass="org.fkjava.mavenqs.App"

上面命令中的org.fkjava.mavenqs.App就是该Maven项目所生成的主类。

执行上面命令,Maven将再次通过网络不断地下载exec插件所需要的各种文件,等exec插件下载完成后,成功执行该插件将可以看到如下输出:

1
Hello World!

上面输出的就是org.fkjava.mavenqs.App类中main()方法的输出结果

你可能会感到好奇:Maven怎么这么神奇呢?这份pom.xml文件如此简单,Maven怎么知道如何编译项目?Maven怎么知道项目源文件放在那里?Maven怎么知道编译生成的二进制文件放在哪里?……

实际上,Maven运行时pom.xml是根据设置组合来运行的,每个Maven项目的pom.xml都有一个上级pom.xml,当前项目的pom.xml的设置信息会被合并到上级pom.xml中,上级pom.xml(相当于Maven默认的pom.xml)定义了该项目大量的默认设置。如果用户希望看到Maven项目实际起作用的pom.xml(也就是上级pom.xml与当前pom.xml合并后的结果),可以运行如下命令:

1
mvn help:effective-pom

第一次运行该命令,Maven也会不断地从网络下载一些文件,然后就会看到一个庞大的、完整的pom.xml文件,它包含Maven大量的默认设置。如果希望改变其中某些默认的设置,也可以在当前项目的pom.xml中定义对应的元素来覆盖上级pom.xml中的默认设置

5 Maven的核心概念

从前面介绍的过程来看,只要将项目的源文件按Maven要求的规范组织,并提供pom.xml文件,即使pom.xml文件中只包含极少的信息,也依然可以使用Maven来编译项目、运行程序,甚至可以运行测试用例、打包项目,这是因为Maven采用了”约定优于配置(Convention over Configuration,CoC)”的原则,根据此原则,Maven的主要约定有如下几条。

  • 源代码应该位于${basedir}/src/main/java路径下
  • 资源文件应该位于${basedir}/src/main/resourse路径下
  • 测试代码应该位于${basedir}/src/test路径下
  • 编译生成的class文件应该位于${basedir/target/classes}路径下
  • 项目应该会产生一个JAR文件,并将生成的JAR包放在${basedir}/target路径下

通过这种约定,就可以避免像Ant构建那牙膏必需为每个子项目定义这些目录。除此之外,Maven对核心插件也使用了一组通用的约定,用来编译源代码、打包可分发的JAR、生成Web站点,以及许多其他的过程

Maven的强大很大程度来自于它的“约定”,Maven月定义了一个固定的生命周期,以及一组用于构建和装配软件的通用插件,如果完全遵守这些约定,Maven只需要将源代码放到正确的目录下,Maven即可处理剩下的事情

使用CoC的一个副作用是,用户可能会觉得他们被强迫使用一种固定的流程和方法,甚至对某些约定反感。不过不用担心,所有遵守CoC原则的技术通常都会提供一种机制允许用户进行配置。以Maven为例,项目源代码的资源文件的位置可以被自定义,JAR文件的名字可以被自定义…..换句话说,如果不想遵守约定,Maven也会自定义默认值来改变约定

5.1 Maven的生命周期(lifecycle)

依然使用前面介绍的mavenQS项目,进入pom.xml文件所在的路径,然后执行如下命令:

1
mvn install

第一次运行该命令同样会看到Maven不断地从网络下载各种插件,下载完成后可以看到该命令将会依次执行如下插件:

上面命令只是告诉Maven运行install,但从实际的运行结果来看,Maven不仅运行了install,而且还在该插件之前运行了大量的插件。这就是Maven生命周期所导致的。

生命周期是指Maven构建项目包含多个有序的阶段(phase),Maven可以支持许多不同的生命周期,最常用的生命周期是Maven默认的生命周期。

Maven生命周期中的元素被称为phase(阶段),每个生命周期由多个阶段组成,Maven生命周期中的各阶段总是按顺序、依次执行,Maven默认的生命周期的开始阶段是验证项目的基本完整性,结束阶段是将项目发布到远程仓库

实际上,mvn命令除了可以使用<plugin-prefix>:<goal>运行指定插件的目标之外,还可以使用如下命令格式:

1
mvm <phase1> <phase2>...

上面命令告诉Maven执行Maven生命周期中的一个或多个阶段。当使用mvn命令告诉Maven执行生命周期的某个阶段时,Maven会自动从生命周期的第一个阶段开始执行,直至mvn命令指定的阶段。

Maven包含三个基本的生命周期。

  • clean生命周期
  • default生命周期
  • site生命周期

clean生命周期用于在构建项目之前进行一些处理工作,该生命周期包含如下三个核心阶段。

  • pre-clean:在构建之前执行预清理
  • clean:执行清理
  • post-clean:最后清理

进入mavenQs项目中pom.xml所在的路径,执行如下命令:

1
mvm post-clean

执行上面命令将会清理项目编译过程中生成的文件,执行该命令后将可以看到mavenQs目录下只剩下src目录和pom.xml文件

默认的生命周期则包含了项目构建的核心部分,默认的生命周期包含如下核心阶段:

  • compile:编译项目
  • test:单元测试
  • package:项目打包
  • install:安装到本地仓库
  • deploy:部署到远程仓库

mvn compilemvn install命令所执行的都是上面列出的阶段。当使用Maven执行mvn install时,是即将会先执行isntall阶段之前的阶段。下图显示了默认的生命周期所包含的核心阶段的执行过程。

上面列出的只是Maven默认生命周期的核心阶段。实际上,Maven默认的生命周期包含如下阶段:

  • validate:验证项目是否正确
  • generate-sources:生成源代码
  • process-sources:处理源代码
  • generate-resources:生成项目所需的资源文件
  • process-resources:复制资源文件至目标目录
  • compile:编译项目的源代码
  • process-classes:处理编译生成的文件
  • generate-test-sources:生成测试源代码
  • process-test-sources:处理测试源代码
  • generate-test-resources:生成测试的资源文件
  • process-test-resources:复制测试的资源文件至测试目标目录

site 生命周期用于生成项目报告站点、发布站点。该生命周期包含如下核心阶段:

  • pre-site:生成站点之前做验证
  • site:生成站点
  • post-site:生成站点之后做验证
  • site-deploy:发布站点到远程服务器

进入mavenQs项目中pom.xml所在的路径,执行如下命令:

1
mvn post-site

第一次执行该命令时,将会看到Maven不断地下载插件及相关文件,成功执行该命令后将可以看到mavenQs目录下多出一个target目录,该目录下包含一个site子目录。打开site子目录下的index.htm,将可以看到如图所示的页面。

注意:如果出现如下报错,在pom.xml中指定对应的版本即可

1
2
// 报错关键字
org.apache.maven.doxia.siterenderer.DocumentContent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
<pluginManagement>
<plugins>
<plugin>
<groupID>org.apache.maven.plugins</groupID>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.9</version>
</plugin>
</plugins>
</pluginManagement>
</build>

5.2 插件和目标(plugins and goal)

除了可以使用Maven官方、第三方提供的各种插件之外,也可以开发自定义插件,通过自定义插件来完成任务。

每个插件又可以包含多个可执行的目标(goal),使用mvn命令执行指定目标的格式如下:

1
mvn <plugin-prefix>:<goal> -D<属性名>=<属性值> ...

当使用mvn运行Maven生命周期的指定阶段时,各阶段所完成的工作其实也是由插件实现的。插件目标可以绑定到生命周期的各阶段上,每个阶段可能绑定了零个或者多个目标。随着Maven沿着生命周期的阶段移动,它会自动执行绑定在各特定阶段上的所有目标。

Maven生命周期的各阶段也是一个抽象的概念,对于软件构建过程来说,默认的生命周期被划分为compile、test、package、install、deploy这5个阶段,但这5个阶段分别运行什么插件、目标,其实是抽象的——这些阶段对于不同项目来说意味着不同的事情。例如,package阶段在某些项目中对应于生成一个JAR,它意味着“将一个项目打成一个JAR包”;而在另一个项目里,package阶段可能对应于生成一个WAR包。

开发时可以将任意插件绑定到指定生命周期,例如将上面的mavenQs项目另外复制一份,并在其pom.xml文件中增加如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<build>
<plugins>
<plugin>
<!-- 下面3个元素顶一个exec插件的坐标 -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<!-- 指定绑定到compile阶段 -->
<phase>compile</phase> <!-- ① -->
<!-- 指定运行exec插件的java目标 -->
<goals>
<goal>java</goal> <!-- ② -->
</goals>
<!-- configuration元素用于为插件的目标配置参数 -->
<configuration>
<!-- 下面元素配置mainClass参数的值为:org.fkjava.mavenqs.App -->
<mainClass>org.fkjava.mavenqs.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

①号配置代码指定该插件、目标绑定到compile阶段;②号配置代码指定运行exec插件的java目标。通过上面这段配置,即可将exec插件的java目标绑定到compile阶段。

进入该项目中pom.xml所在的路径,然后执行命令:

1
mvn compile

执行上面命令不仅可以看到Maven执行compile插件的compile目标来编译项目,还可以看到Maven执行exec插件的java目标来运行项目的org.fkjava.mavenqs.App

5.3 Maven的坐标(coordinate)

POM需要为项目提供一个唯一标识符,这个标识符就被称为Maven坐标,Maven坐标由4个元素组成。

  • groupId:该项目的开发者的域名
  • artifactId:指定项目名
  • package:指定项目打包的类型
  • version:指定项目的版本

例如,mavenQs项目的pom.xml文件中如下配置定义了该项目的Maven坐标:

1
2
3
4
<groupId>org.fkjava</groupId>
<artifactId>mavenQs</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

Maven坐标可用于精确定位一个项目,例如mavenQs项目中还有如下配置片段:

1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>

上面配置片段定义了一个依赖关系,这段配置表明该项目依赖于junit3.8.1,其中的2-4行代码就是junit项目的坐标。

Maven坐标通常英文冒号作为分隔符来书写,即以groupId:artifactId:packaging:version格式书写。例如mavenQs项目的坐标可写成org.fkjava.mavenQs:jar:1.0-SNAPSHOT。而mavenQs项目所依赖的项目的坐标则可写成junit:junit:jar:3.8.1

5.4 Maven的资源库(reposity)

第一行运行Maven时,Maven会自动从远程资源库下载很多文件,包括各种Maven插件,以及项目所以来的库。实际上,初始的Maven工具非常小,这是因为Maven工具本身的功能非常有限,几乎所有功能都是由Maven插件完成的。

Maven资源库用于保存Maven插件, 以及各种第三方框架。简单来说,Maven用到的插件、项目依赖的各种JAR包,都会保存在资源库中。

Maven资源库可分为如下三种:

  • 本地资源库:Maven用到的所有插件、第三方框架都会下载到本地库。只有当本地库中找不到时,才采取从远程下载。可以通过Maven安装目录下的conf\settings.xml文件,或者用户Home目录下的m2\settings.xml文件中的<localReposity.../>元素进行设置。
  • 远程资源库:远程资源库通常由公司或团队进行集中维护。通过远程资源库,可以让全公司的项目使用相同的JAR包系统
  • 中央资源库(默认):中央资源库由Maven官方维护,中央资源库包括了各种公开的Maven插件、各种第三方项目。几乎所有的开源项目都会选择中央资源库发布框架。

当Maven需要使用某个插件或JAR包时,Maven的搜索顺序为:本地资源库->远程资源库->中央资源库,当Maven从中央资源库下载了某个插件或JAR包时,Maven都会自动在本地资源库中保存它们,因此只有当Maven第一次使用某个插件或JAR包时,才需要通过网络下载。

6 依赖管理

下面使用Maven开发一个简单的Struts2项目。

Step 1:使用如下命令创建一个Web项目

1
mvn archetype:generate -DgroupId=org.ohmybug -DartifactId=struts2qs -Dpackage=org.ohmybug.struts2qs -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

通过上面命令创建的项目具有如下结构:

1
2
3
4
5
6
7
struts2qs
└─src
└─main
├─resources
└─webapp
└─WEB-INF
└─web.xml

其中WEB-INF路径和web.xml文件就是Web应用必需的文件夹和配置文件。

接下来打开struts2qs目录下的pom.xml文件,在该文件中添加如下配置信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<name>struts2qs</name>
<url>http://www.ohmybug.org</url>

<!-- 定义该项目所使用的License -->
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<!-- 声明该项目所属的组织 -->
<organization>
<name>OhMyBug</name>
<url>http://www.ohmybug.org</url>
</organization>
<!-- 声明项目开发者 -->
<developers>
<developer>
<id>ohmybug</id>
<name>ohmybug</name>
<email>ohmybug@163.com</email>
<url>http://www.ohmybug.org</url>
<organization>OhMyBug</organization>
<!-- 声明开发者的角色 -->
<roles>
<role>developer</role>
</roles>
<timezone>+8</timezone>
</developer>
</developers>
<!-- 声明对项目有贡献的人 -->
<contributors>
<contributor>
<name>ohmybug</name>
<email>ohmybug@163.com</email>
<url>http://www.ohmybug.org</url>
<organization>ohmybug</organization>
<roles>
<role>developer</role>
</roles>
</contributor>
</contributors>

上面配置信息用于定制该项目的配置信息,这段配置信息指定了该项目遵守的License,并制定了该项目所属的组织、项目的开发者,以及对项目有贡献的人。这些信息都用于定制该Maven项目,这些信息主要起描述性作用。

为该项目增加Struts 2的支持,可以在pom.xml中的<dependencies.../>元素内增加<dependency.../>元素——每个<dependency.../>元素定义了一个依赖框架或依赖类库。

<dependency.../>元素可接受如下子元素:

  • <groupId.../>:指定依赖框架或依赖类库所属组织ID
  • <artifactId.../>:指定依赖框架或依赖类库的项目名
  • <version.../>:指定依赖框架或依赖类库的版本号
  • <scope.../>:指定依赖库起作用的范围。该子元素可接受compile、provided、test、system、runtime、import等值
  • <type.../>:指定依赖框架或依赖类库的类型,该元素的默认值是jar。另外,还可以只指定war、ejb-client、test-jar等值
  • <optional.../>:该元素指定该依赖库是否为可选的
  • <classifier.../>:JDK版本号,如jdk14或hdk15等。用于指定被依赖的JAR包是在哪个版本下编译的。
  • <exclusions../>:该元素用于排除依赖

<scope.../>元素用于指定依赖库起作用的范围,该元素可指定如下值:

  • compile:默认的范围,编译、测试、打包时需要
  • provided:表示容器会在runtime时提供
  • runtime:表示编译时不需要,但测试和运行时需要,最终打包会包含进去
  • test:只用于测试阶段
  • system:与provided类似,但要求该JAR是系统中自带的
  • import:继承父POM文件中用dependencyManagement配置的依赖,import范围只能在dependencyManagement元素中使用(为了解决多继承)

关于Maven的依赖配置需要说明的是,Maven依赖管理具有传递性,比如配置文件设置了项目依赖于a.jar,而a.jar又依赖于b.jar,那么该项目无需显示声明依赖于b.jar,Maven会自动管理这种依赖的传递

由于Maven的依赖管理具有传递性,因此有时需要用<exclusion.../>子元素排除指定的依赖,例如如下配置:

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>javax.activation</groupId>
<artifactId>mail</artifactId>
<type>jar</type>
<exclusions>
<exclusion>
<artifactId>activation</artifactId>
<groupId>javax.activation</groupId>
</exclusion>
</exclusions>
</dependency>

上面配置指定该项目依赖于mail.jar,由于Maven的依赖具有传递性,因此Maven会自动将mail.jar以来的activation.jar也依赖进来。为了将activation.jar排除出去,即可进行如上面配置文件所示的配置。

掌握依赖关系的配置方法之后,接下来可以在strut2qs项目的pom.xml文件的<dependencies.../>元素中增加如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 配置该项目依赖Struts 2 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<!-- 此处指定依赖的Struts 2版本 -->
<version>2.5.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>

每个框架的坐标除了可以通过该框架自身的文档获取之外,也可以登录http://search.maven.org站点查询

进入struts2qs项目的pom.xml文件所在的路径,执行如下命令:

1
mvn package

由于此时Maven项目中的文件组织形式符合Web应用的格式,而且pom.xml文件中<packaging…/>元素的值为war,因此执行上面命令将会把该项目打包成WAR包。

执行上面命令同样也会从网络上下载插件和文件,当该命令执行成功后即可在target目录下看到一个struts2qs.war文件,如果用WinRAR工具解压该文件,即可看到该压缩包内WEB-INF\lib中包含了Struts 2框架的各种JAR包,如图。

从图中可以看出使用Maven之后,只需要在pom.xml文件中配置该项目依赖Struts 2,剩下的事情就交给Maven搞定,无需关心Struts 2的官网,无需关心从哪里下载Struts 2的JAR包,所有依赖关系都交给Maven处理即可。

文章目录
  1. 1 前言
  2. 2 下载和安装Maven
  3. 3 设置Maven
  4. 4 创建、构建简单的项目
  5. 5 Maven的核心概念
    1. 5.1 Maven的生命周期(lifecycle)
    2. 5.2 插件和目标(plugins and goal)
    3. 5.3 Maven的坐标(coordinate)
    4. 5.4 Maven的资源库(reposity)
  6. 6 依赖管理
|