1 前言
Maven是一个比Ant更先进的项目管理工具,它采用一种“约定优于配置(CoC)”的策略来管理项目。它不仅用于把源代码构建成可发布的项目(包括编译、打包、测试和分发),还可以生成报告、生成Web站点等。
2 下载和安装Maven
下载和安装Maven按如下步骤进行:
Step 1:登录Maven站点下载Maven最新版。虽然Maven是基于Java的生成工具,具有平台无关的特性,但考虑到解压缩的方便性,通常建议Windows平台下载*.zip压缩包,而Linux平台下载.gz压缩包。
Step 2:将下载的压缩文件解压缩到任意路径,解压缩后看到如下文件结构:
- bin:保存Maven的可执行命令。其中
mvn
和mvn.bat
就是执行Maven工具的命令。 - boot:该目录只包含一个
plexus-classworlds-2.6.0.jar
。plexus-classworlds
是一个类加载器框架,与默认的Java类加载器相比,它提供了更丰富的语法以方便配置,Maven使用该框架加载自己的类库。通常无需理会。 - conf:保存Maven配置文件的目录,该目录包含
settings.xml
文件,该文件用于设置Maven的全局行为。通常建议将该文件复制到~/.m2/
目录下(~表示用户目录),这样可以只设置当前用户的Maven行为。 - lib:该目录包含了所有Maven运行时需要的类库,Maven本身是分模块开发的,因此用户能看到诸如
maven-core-3.6.3.jar
、maven-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 | <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-id
、plugin-artifact-id
、plugin-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 | mavenQs |
上面项目中的App.java是archetype插件生成的一个简单的Java类,而AppTest则是该插件App生成的测试用力
除此之外,还可以看到该项目的根路径下包含一个pom.xml文件,该文件的作用类似于Ant的build.xml文件,但它的内容比build.xml文件的内容简洁得多
打开pom.xml文件可以看到如下内容:
1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
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 | <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 compile
、mvn 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 | // 报错关键字 |
1 | <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 | <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 | <groupId>org.fkjava</groupId> |
Maven坐标可用于精确定位一个项目,例如mavenQs项目中还有如下配置片段:
1 | <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 | struts2qs |
其中WEB-INF路径和web.xml文件就是Web应用必需的文件夹和配置文件。
接下来打开struts2qs目录下的pom.xml文件,在该文件中添加如下配置信息。
1 | <name>struts2qs</name> |
上面配置信息用于定制该项目的配置信息,这段配置信息指定了该项目遵守的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 | <dependency> |
上面配置指定该项目依赖于mail.jar,由于Maven的依赖具有传递性,因此Maven会自动将mail.jar以来的activation.jar也依赖进来。为了将activation.jar排除出去,即可进行如上面配置文件所示的配置。
掌握依赖关系的配置方法之后,接下来可以在strut2qs项目的pom.xml文件的<dependencies.../>
元素中增加如下配置:
1 | <!-- 配置该项目依赖Struts 2 --> |
每个框架的坐标除了可以通过该框架自身的文档获取之外,也可以登录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处理即可。