Maven学习实战_yukiyama

本文总结自 尚硅谷2022版Maven教程(maven入门+高深,全网无出其右!)

操作环境为 macOS Monterey 12.6 / apache-maven-3.8.5 / IntelliJ IDEA 2022.2.1 (Ultimate Edition) 。


Maven简述

Maven 是 Apache 基金会维护的针对 Java 项目构建和依赖管理的工具,用于定义项目结构、管理项目依赖并提供一套标准的项目构建流程。

  • Maven 作为依赖管理工具。通过引入「依赖」可自动从该依赖的官方网站上下载规范的相关 Jar 包,并管理规模巨大的 jar 包及它们之间的依赖关系。
  • Maven 作为构建管理工具。脱离 IDE 环境时可利用 Maven 进行构建。

坐标

Maven 项目使用 pom.xml 文件来管理依赖。该文件中的 <dependencies> 标签中,每一个 <dependency> 都通过三个向量来完成依赖。

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-clean-plugin -->
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
</dependency>

这三个向量唯一确定一个 jar 包。

向量 描述
groupId 公司或组织的项目 ID,例如 org.apache.maven.plugins
artifactId 项目或项目中的模块,例如maven-clean-plugin
version 版本号,例如 2.5, 1.0-SNAPSHOT, 2.0-RELEASE 等。
SNAPSHOT 为快照版本,即还在开发迭代中的不稳定版本。
RELEASE 为正式版本。

根据该依赖,如下文件会自动下载到本地仓库 (本演示为 repo ) 中的如下目录中。可以看到,路径实际上是由 groupId, artifactIdversion 组成的。

1
2
3
4
5
6
7
/Users/yukiyama/maven/repo/org/apache/maven/plugins/maven-clean-plugin/2.5

_remote.repositories
maven-clean-plugin-2.5.jar
maven-clean-plugin-2.5.jar.sha1
maven-clean-plugin-2.5.pom
maven-clean-plugin-2.5.pom.sha1

POM

POM (Project Object Model) ,即 「项目对象模型」 。可与之类比的是 XML 文档中的 DOM 的概念 (Document Object Model) ,文档对象模型。POM 将项目抽象为模型体现在项目的 pom.xml 文件中。常用的 pom 标签会在后文中陆续介绍。


目录结构

Maven 项目的目录结构是约定好的,约定目录的目的是尽可能 自动化完成项目构建 。例如 Maven 执行编译操作,要先去 Java 源程序目录读取 Java 源代码,然后执行编译,之后将编译结果存放在 target 目录中等等。不同的 Maven 项目的约定的目录结构不同,在后续分别创建「Maven Java 项目」和 「Maven Web 项目」时将分别展示二者的目录结构。

当前开发领域的技术发展趋势:约定大于配置,配置大于编码


安装及配置

安装Maven

Mac

  1. Maven 官网下载所需版本的 Maven 压缩包。

    1
    apache-maven-3.8.6-bin.tar.gz
  2. 将压缩包解压后置于一个无特殊字符 (如中文字符) 的路径下。

  3. 在终端中通过 vim ~/.bash_profile 命令编辑配置文件 .bash_profile ,向其中 PATH 中添加 Maven 的路径信息,如下 (Java 已事先安装好并配置到环境变量中了)。

    1
    2
    3
    4
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home
    export M2_HOME=/Users/yukiyama/apache-maven-3.8.5/

    export PATH=${PATH}:${JAVA_HOME}/bin:${M2_HOME}/bin
  4. 保存并退出后,在终端中执行 source .bash_profile 使新配置生效。

  5. 在终端中执行 echo $M2_HOME ,应返回 Maven 的路径信息。另外,还可执行 mvn --version ,若安装成功,则返回已安装的 Maven 的版本信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    yukiyama@yukiyama ~ % echo $M2_HOME
    /Users/yukiyama/apache-maven-3.8.5/
    yukiyama@yukiyama ~ % mvn --version
    Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
    Maven home: /Users/yukiyama/apache-maven-3.8.5
    Java version: 16.0.1, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home
    Default locale: zh_JP_#Hans, platform encoding: UTF-8
    OS name: "mac os x", version: "11.5", arch: "x86_64", family: "mac"
    yukiyama@yukiyama ~ %

配置Maven

maven 的配置文件在 maven 安装目录下 (apache-maven-x.x.x) 的 conf 文件夹中,文件名为 settings.xml 。常用配置如下。

标签 描述
<localRepository> 本地仓库路径
<mirrors> 镜像仓库

指定本地仓库路径

settings.xml 中搜索 <localRepository> 标签,设置本地仓库路径。

1
<localRepository>/Users/yukiyama/maven/repo</localRepository>

添加镜像仓库

搜索 <mirrors> 标签,注释掉现有的 <mirror> 标签内的内容,然后在 <mirrors> 标签内新增阿里云提供的镜像仓库。

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

指定 JDK 版本

搜索 <profiles> 标签,添加如下内容可以指定 JDK 版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 使用 JDK1.8 -->
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>

创建及管理项目

命令行方式

创建Java项目

在终端中进入需要创建项目的目录下,执行 mvn archetype:generate 命令 创建 Maven Java 项目

  1. 初次使用时会下载依赖的 Jar 包,且从下载地址中看到是从我们配置的 aliyun 镜像中下载的。
  2. 下载完成后提示 Choose archetype ,需要输入 1 到 8 选择 Maven 项目模版。若直接回车则选择默认的第 7 个模版 maven-archetype-quickstart
  3. 接着分别设置 groupId, artifactId, version, package
  4. 确认后输入 Y 或直接回车完成。
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
45
46
47
48
49
50
yukiyama@yukiyama ~ % cd /Users/yukiyama/maven/workspace/test
yukiyama@yukiyama test % mvn archetype:generate
[INFO] Scanning for projects...
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom
...(省略)...
[INFO] Generating project in Interactive mode
[WARNING] No archetype found in remote catalog. Defaulting to internal catalog
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: internal -> org.apache.maven.archetypes:maven-archetype-archetype (An archetype which contains a sample archetype.)
2: internal -> org.apache.maven.archetypes:maven-archetype-j2ee-simple (An archetype which contains a simplifed sample J2EE application.)
3: internal -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.)
4: internal -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site.
This archetype can be layered upon an existing Maven plugin project.)
5: internal -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sample JSR-268 Portlet.)
6: internal -> org.apache.maven.archetypes:maven-archetype-profiles ()
7: internal -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)
8: internal -> org.apache.maven.archetypes:maven-archetype-site (An archetype which contains a sample Maven site which demonstrates
some of the supported document types like APT, XDoc, and FML and demonstrates how
to i18n your site. This archetype can be layered upon an existing Maven project.)
9: internal -> org.apache.maven.archetypes:maven-archetype-site-simple (An archetype which contains a sample Maven site.)
10: internal -> org.apache.maven.archetypes:maven-archetype-webapp (An archetype which contains a sample Maven Webapp project.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 7:
Define value for property 'groupId': com.yukiyama.maven
Define value for property 'artifactId': pro01-maven-java
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.yukiyama.maven: :
Confirm properties configuration:
groupId: com.yukiyama.maven
artifactId: pro01-maven-java
version: 1.0-SNAPSHOT
package: com.yukiyama.maven
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: /Users/yukiyama/maven/workspace/test
[INFO] Parameter: package, Value: com.yukiyama.maven
[INFO] Parameter: groupId, Value: com.yukiyama.maven
[INFO] Parameter: artifactId, Value: pro01-maven-java
[INFO] Parameter: packageName, Value: com.yukiyama.maven
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/yukiyama/maven/workspace/test/pro01-maven-java
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 06:29 min
[INFO] Finished at: 2022-09-22T02:20:01+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama test %

创建完成后在项目目录下可以看到该项目模版的目录结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yukiyama@yukiyama test % tree pro01-maven-java
pro01-maven-java
├── pom.xml
└── src
├── main
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── App.java
└── test
└── java
└── com
└── yukiyama
└── maven
└── AppTest.java

目录用途如下。

目录 描述
src 源码目录
main 主体程序目录
java Java源码 (.java 文件)
com package 目录
test 测试程序目录

在我们指定的本地仓库中 (repo 文件夹) ,可以看到很多因为本次项目创建而引入的 Jar 包及相关文件。例如对于第一个下载的文件,其下载后的路径如下。

1
2
3
4
5
// 下载的第一个文件
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom

// 下载后的路径
repo/org/apache/maven/plugins/maven-clean-plugin/2.5/maven-clean-plugin-2.5.pom

从这里可以看出,路径实际上是由 groupId, artifactIdversion 组成的。


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
<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.yukiyama.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>pro01-maven-java</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

自动生成的 pom.xml 中依赖的 junit 版本 3.8.1 较低,可按需要改为较新版本,如 4.12 版本。


项目构建

需要在 pom.xml 文件所在目录下执行构建命令,否则出现如下错误 (… but there is no POM in this directory …)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yukiyama@yukiyama test % mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.107 s
[INFO] Finished at: 2022-09-22T20:14:54+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] The goal you specified requires a project to execute but there is no POM in this directory (/Users/yukiyama/maven/workspace/test). Please verify you invoked Maven from the correct directory. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MissingProjectException
yukiyama@yukiyama test %

编译

在 Maven 项目的 pom.xml 所在目录下执行 mvn complie 完成编译。首次执行此命令会下载相关 Jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
yukiyama@yukiyama pro01-maven-java % mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
...(略)...
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:17 min
[INFO] Finished at: 2022-09-22T16:20:01+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

编译完成后可以看到在项目目录下多了 target 文件夹,编译后的 .class 即存放 target/classes 文件夹下。

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
pro01-maven-java
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── Calculator.java
│   └── test
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── CalculatorTest.java
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── Calculator.class
├── generated-sources
│   └── annotations
└── maven-status
└── maven-compiler-plugin
└── compile
└── default-compile
├── createdFiles.lst
└── inputFiles.lst

测试

执行 mvn test 可以完成测试。同样地,首次执行时会下载相关 Jar 包 (如下执行已经不是首次执行,所以没有下载 Jar 包的记录)。

可以看到,在执行 test 命令之前,实际上 Maven 还自动依次执行了 resources, compile, testResources, testCompile

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
yukiyama@yukiyama pro01-maven-java % mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ pro01-maven-java ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ pro01-maven-java ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ pro01-maven-java ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ pro01-maven-java ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ pro01-maven-java ---
[INFO] Surefire report directory: /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/surefire-reports

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.yukiyama.maven.CalculatorTest
完成测试。
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.103 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.365 s
[INFO] Finished at: 2022-09-24T14:20:57+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

测试完成后可以看到 target 文件夹中多了 test-classes 目录,存放测试源文件编译后的 .class 文件。此外还生成了测试报告,存放于 surefire-reports 文件夹中。

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
pro01-maven-java
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── Calculator.java
│   └── test
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── CalculatorTest.java
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── Calculator.class
├── generated-sources
│   └── annotations
├── generated-test-sources
│   └── test-annotations
├── maven-status
│   └── maven-compiler-plugin
│   ├── compile
│   │   └── default-compile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   └── testCompile
│   └── default-testCompile
│   ├── createdFiles.lst
│   └── inputFiles.lst
├── surefire-reports
│   ├── TEST-com.yukiyama.maven.CalculatorTest.xml
│   └── com.yukiyama.maven.CalculatorTest.txt
└── test-classes
└── com
└── yukiyama
└── maven
└── CalculatorTest.class

清理

执行 mvn clean 清理当前目录的编译结果。同样地,首次执行时会下载相关 Jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yukiyama@yukiyama pro01-maven-java % mvn clean
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ pro01-maven-java ---
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/3.0/plexus-utils-3.0.pom
...(略)...
[INFO] Deleting /Users/yukiyama/maven/workspace/test/pro01-maven-java/target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.845 s
[INFO] Finished at: 2022-09-22T16:36:34+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

清理后可看到 target 文件夹已删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pro01-maven-java
├── pom.xml
└── src
├── main
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── Calculator.java
└── test
└── java
└── com
└── yukiyama
└── maven
└── CalculatorTest.java

打包

执行 mvn package 打包项目为 Jar 包。同样地,首次执行时会下载相关 Jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yukiyama@yukiyama pro01-maven-java % mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-jar-plugin/2.4/maven-jar-plugin-2.4.pom
...(略)...
[INFO] Building jar: /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/pro01-maven-java-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.557 s
[INFO] Finished at: 2022-09-22T16:40:38+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

打包完成后在 target 目录下可以看到生成了如下 Jar 包,文件名是由 artifactIdversion 组成的。

1
pro01-maven-java-1.0-SNAPSHOT.jar

解压缩后可看到 Jar 包的如下构成,其中并不包含测试程序的字节码文件。

1
2
3
4
5
6
7
8
9
10
11
12
pro01-maven-java-1.0-SNAPSHOT
├── META-INF
│   ├── MANIFEST.MF
│   └── maven
│   └── com.yukiyama.maven
│   └── pro01-maven-java
│   ├── pom.properties
│   └── pom.xml
└── com
└── yukiyama
└── maven
└── Calculator.class

其中 pom.xml 文件与原项目中的相同,pom.properties 文件如下。

1
2
3
4
5
#Generated by Maven
#Thu Sep 22 16:40:38 CST 2022
groupId=com.yukiyama.maven
artifactId=pro01-maven-java
version=1.0-SNAPSHOT

安装

执行 mvn install 安装 Jar 包到本地仓库中。从下面的执行日志可看到,在执行安装前,该命令会先完成编译,测试编译,以及测试动作。

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
45
46
47
48
49
50
yukiyama@yukiyama pro01-maven-java % mvn install
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ pro01-maven-java ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ pro01-maven-java ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ pro01-maven-java ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ pro01-maven-java ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ pro01-maven-java ---
[INFO] Surefire report directory: /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/surefire-reports

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.yukiyama.maven.CalculatorTest
完成测试。
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.09 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ pro01-maven-java ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ pro01-maven-java ---
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/3.0.5/plexus-utils-3.0.5.pom
...(略)...
[INFO] Installing /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/pro01-maven-java-1.0-SNAPSHOT.jar to /Users/yukiyama/maven/repo/com/yukiyama/maven/pro01-maven-java/1.0-SNAPSHOT/pro01-maven-java-1.0-SNAPSHOT.jar
[INFO] Installing /Users/yukiyama/maven/workspace/test/pro01-maven-java/pom.xml to /Users/yukiyama/maven/repo/com/yukiyama/maven/pro01-maven-java/1.0-SNAPSHOT/pro01-maven-java-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.432 s
[INFO] Finished at: 2022-09-22T16:55:49+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

我们已经知道,无论执行的是 test, package, install 或是其他命令,maven 默认都会「覆盖式」地按既定执行顺序从最开始的阶段到命令所指定的阶段。若希望跳过某个阶段,可加入 -D 参数,举例如下 (-Dmaven 之间无空格)。

1
mvn clean install -Dmaven.test.skip=true

该命令表示执行 mvn clean install 时跳过 test 阶段。

1
mvn clean compile -Dmaven.clean.skip=true -Dmaven.validate.skip=true

该命令表示执行 mvn clean compile 时跳过 cleanvalidate 阶段。

安装到本地仓库中的路径是根据该项目的坐标生成的。在本地仓库 repo 目录下,可以看到如下文件结构。安装到本地仓库后的 Jar 包文件名不变,但 pom.xml 变为 pro01-maven-java-1.0-SNAPSHOT.pom ,它们内容相同。

1
2
3
4
5
6
7
8
9
10
com
└── yukiyama
└── maven
└── pro01-maven-java
├── 1.0-SNAPSHOT
│   ├── _remote.repositories
│   ├── maven-metadata-local.xml
│   ├── pro01-maven-java-1.0-SNAPSHOT.jar
│   └── pro01-maven-java-1.0-SNAPSHOT.pom
└── maven-metadata-local.xml

此外,还可以使用 mvn clean install 完成安装,实际效果等同于先执行 mvn clean 再执行 mvn install


创建Web项目

在终端中进入工作目录下,执行如下命令创建 Maven Web 项目 (参考 Maven 官网 Maven Webapp Archetype)。

1
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4
  1. 初次使用时会下载依赖的 Jar 包,且从下载地址中看到是从我们配置的 aliyun 镜像中下载的。
  2. 下载完成后根据提示设置 groupId, artifactId, version, package 或直接回车使用默认值。
  3. 确认后输入 Y 或直接回车完成。
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
45
46
47
48
yukiyama@yukiyama test % mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.4
[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.2.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.2.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.2.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[WARNING] No archetype found in remote catalog. Defaulting to internal catalog
[INFO] Archetype repository not defined. Using the one from [org.apache.maven.archetypes:maven-archetype-webapp:1.0] found in catalog internal
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/archetypes/maven-archetype-webapp/1.4/maven-archetype-webapp-1.4.pom
...(略)...
Define value for property 'groupId': com.yukiyama.maven
Define value for property 'artifactId': pro02-maven-web
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.yukiyama.maven: :
Confirm properties configuration:
groupId: com.yukiyama.maven
artifactId: pro02-maven-web
version: 1.0-SNAPSHOT
package: com.yukiyama.maven
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-webapp:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.yukiyama.maven
[INFO] Parameter: artifactId, Value: pro02-maven-web
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.yukiyama.maven
[INFO] Parameter: packageInPathFormat, Value: com/yukiyama/maven
[INFO] Parameter: package, Value: com.yukiyama.maven
[INFO] Parameter: groupId, Value: com.yukiyama.maven
[INFO] Parameter: artifactId, Value: pro02-maven-web
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Project created from Archetype in dir: /Users/yukiyama/maven/workspace/test/pro02-maven-web
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 39.864 s
[INFO] Finished at: 2022-09-22T17:21:41+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama test %

创建完成后在项目目录下可以看到该项目模版的目录结构。

1
2
3
4
5
6
7
8
pro02-maven-web
├── pom.xml
└── src
└── main
└── webapp
├── WEB-INF
│   └── web.xml
└── index.jsp

目录用途如下。需要注意的时,不同于 archetype-quickstart ,archetype-webapp 不会自动生成 test 目录,若需要,需手动创建。

目录 描述
src 源码目录
main 主体程序目录
webapp web 应用目录

pom.xml

可以看到打包方式 ( <package> 标签) 与之前的 Java 项目不同,为 war 方式。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version="1.0" encoding="UTF-8"?>

<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.yukiyama.maven</groupId>
<artifactId>pro02-maven-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>pro02-maven-web Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<finalName>pro02-maven-web</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

web.xml

1
2
3
4
5
6
7
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

准备
新建Java文件

由于前述创建项目的命令未帮助我们创建 Java 源文件,需要手动创建,如下,我们在 src/main 下创建 java/com/yukiyama/maven 路径,然后创建如下 HelloServlet.java 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.yukiyama.maven;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;

public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write("hello maven web");
}
}

注册Servlet

将如下 xml 标签内容添加到 web.xml 中的 <web-app> 下。

1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.atguigu.maven.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>

编写超链接

在 index.jsp 中写入超链接 <a href="helloServlet">Access Servlet</a>

1
2
3
4
5
6
7
<html>
<body>
<h2>Hello World!</h2>
<!-- 添加超链接 -->
<a href="helloServlet">Access Servlet</a>
</body>
</html>

项目构建

与构建 Maven Java 项目一样,需要在 pom.xml 文件所在命令下执行构建命令。


编译

在 Maven 项目的 pom.xml 所在目录下执行 mvn complie 完成编译,首次执行此命令会下载相关 Jar 包。执行后可能出现如下错误。

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
yukiyama@yukiyama pro02-maven-web % mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-resources-plugin/3.0.2/maven-resources-plugin-3.0.2.pom
...(略:Jar 包下载)...
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro02-maven-web/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /Users/yukiyama/maven/workspace/test/pro02-maven-web/src/main/java/com/yukiyama/maven/HelloServlet.java:[3,26] package javax.servlet.http does not exist
...(略:多条错误信息)...
[INFO] 8 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:27 min
[INFO] Finished at: 2022-09-22T20:02:13+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project pro02-maven-web: Compilation failure: Compilation failure:
...(略:多条错误信息)...
yukiyama@yukiyama pro02-maven-web %

失败是由于缺少 servlet-api.jar 依赖导致的。可以在 mvnrepository 网站 查找该依赖的坐标信息,将其添加到 pom.xml<dependencies> 标签下。

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

再重新执行 mvn compile 命令,可以看到,下载了 servlet-api Jar 包及其他相关文件,之后成功完成。

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
yukiyama@yukiyama pro02-maven-web % mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.pom (14 kB at 3.8 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/net/java/jvnet-parent/3/jvnet-parent-3.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/net/java/jvnet-parent/3/jvnet-parent-3.pom (4.8 kB at 5.5 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar (96 kB at 39 kB/s)
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ pro02-maven-web ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro02-maven-web/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ pro02-maven-web ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro02-maven-web/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.455 s
[INFO] Finished at: 2022-09-22T20:19:53+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

编译完成后可以看到在项目目录下多了 target 文件夹,编译后的 .class 即存放在 target/classes 文件夹下。

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
pro02-maven-web
├── pom.xml
├── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── HelloServlet.java
│   └── webapp
│   ├── WEB-INF
│   │   └── web.xml
│   └── index.jsp
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── HelloServlet.class
├── generated-sources
│   └── annotations
└── maven-status
└── maven-compiler-plugin
└── compile
└── default-compile
├── createdFiles.lst
└── inputFiles.lst

清理

执行 mvn clean 清理当前目录的编译结果。同样地,首次执行时会下载相关 Jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yukiyama@yukiyama pro02-maven-web % mvn clean
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-clean-plugin/3.1.0/maven-clean-plugin-3.1.0.pom
...(略)...
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ pro02-maven-web ---
[INFO] Deleting /Users/yukiyama/maven/workspace/test/pro02-maven-web/target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.774 s
[INFO] Finished at: 2022-09-22T20:26:09+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

清理后可看到 target 文件夹已删除。

1
2
3
4
5
6
7
8
9
10
11
12
13
pro02-maven-web
├── pom.xml
└── src
└── main
├── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── HelloServlet.java
└── webapp
├── WEB-INF
│   └── web.xml
└── index.jsp

打包

执行 mvn package 或者 mvn clean package 打包项目为 war 包。同样地,首次执行时会下载相关 Jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
yukiyama@yukiyama pro02-maven-web % mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/plugins/maven-surefire-plugin/2.22.1/maven-surefire-plugin-2.22.1.pom
...(略)...
[INFO] Packaging webapp
[INFO] Assembling webapp [pro02-maven-web] in [/Users/yukiyama/maven/workspace/test/pro02-maven-web/target/pro02-maven-web]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/yukiyama/maven/workspace/test/pro02-maven-web/src/main/webapp]
[INFO] Webapp assembled in [107 msecs]
[INFO] Building war: /Users/yukiyama/maven/workspace/test/pro02-maven-web/target/pro02-maven-web.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:04 min
[INFO] Finished at: 2022-09-22T20:33:18+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

打包完成后在 target 目录下可以看到生成了如下 war 包 pro02-maven-web.war 及其解压后的文件夹。war 包文件名即 artifactId

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
pro02-maven-web
├── pom.xml
├── src
│   └── main
│   ├── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── HelloServlet.java
│   └── webapp
│   ├── WEB-INF
│   │   └── web.xml
│   └── index.jsp
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── HelloServlet.class
├── generated-sources
│   └── annotations
├── maven-archiver
│   └── pom.properties
├── maven-status
│   └── maven-compiler-plugin
│   └── compile
│   └── default-compile
│   ├── createdFiles.lst
│   └── inputFiles.lst
├── pro02-maven-web
│   ├── META-INF
│   ├── WEB-INF
│   │   ├── classes
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── HelloServlet.class
│   │   └── web.xml
│   └── index.jsp
└── pro02-maven-web.war

测试

首先在此 web 工程下添加之前创建的 java 工程。做法是在 pom.xml 中添加如下 <dependency> 内容。

注意,<scope> 表示该依赖的范围,默认是 compile ,因此可以不写。

1
2
3
4
5
6
7
<!-- 导入 Maven Java 工程依赖 -->
<dependency>
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

接着执行 mvn test 完成测试。同样地,首次执行时会下载相关 Jar 包。

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
45
46
47
48
yukiyama@yukiyama pro02-maven-web % mvn test
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ pro02-maven-web ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro02-maven-web/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ pro02-maven-web ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ pro02-maven-web ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro02-maven-web/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ pro02-maven-web ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro02-maven-web/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ pro02-maven-web ---
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-junit4/2.22.1/surefire-junit4-2.22.1.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-junit4/2.22.1/surefire-junit4-2.22.1.pom (3.1 kB at 1.9 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-providers/2.22.1/surefire-providers-2.22.1.pom
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-providers/2.22.1/surefire-providers-2.22.1.pom (2.5 kB at 3.6 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-junit4/2.22.1/surefire-junit4-2.22.1.jar
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/surefire/surefire-junit4/2.22.1/surefire-junit4-2.22.1.jar (85 kB at 123 kB/s)
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.yukiyama.maven.CalculatorTest
完成测试。
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.076 s - in com.yukiyama.maven.CalculatorTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.989 s
[INFO] Finished at: 2022-09-24T14:44:38+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

测试完成后可以看到 target 文件夹中多了 test-classes 目录,存放测试源文件编译后的 .class 文件。此外还生成了测试报告,存放于 surefire-reports 文件夹中。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
pro02-maven-web
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── HelloServlet.java
│   │   └── webapp
│   │   ├── WEB-INF
│   │   │   └── web.xml
│   │   └── index.jsp
│   └── test
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── CalculatorTest.java
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── HelloServlet.class
├── generated-sources
│   └── annotations
├── generated-test-sources
│   └── test-annotations
├── maven-archiver
│   └── pom.properties
├── maven-status
│   └── maven-compiler-plugin
│   ├── compile
│   │   └── default-compile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   └── testCompile
│   └── default-testCompile
│   ├── createdFiles.lst
│   └── inputFiles.lst
├── pro02-maven-web
│   ├── META-INF
│   ├── WEB-INF
│   │   ├── classes
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── HelloServlet.class
│   │   └── web.xml
│   └── index.jsp
├── pro02-maven-web.war
├── surefire-reports
│   ├── TEST-com.yukiyama.maven.CalculatorTest.xml
│   └── com.yukiyama.maven.CalculatorTest.txt
└── test-classes
└── com
└── yukiyama
└── maven
└── CalculatorTest.class

再次打包

再次执行 mvn package 或者 mvn clean package 再次打包项目,可以看到,除了生成 war 包外,所依赖的 Java 项目被打包在 /target/pro02-maven-web/WEB-INF/lib 下。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
pro02-maven-web
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── HelloServlet.java
│   │   └── webapp
│   │   ├── WEB-INF
│   │   │   └── web.xml
│   │   └── index.jsp
│   └── test
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── CalculatorTest.java
└── target
├── classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── HelloServlet.class
├── generated-sources
│   └── annotations
├── generated-test-sources
│   └── test-annotations
├── maven-archiver
│   └── pom.properties
├── maven-status
│   └── maven-compiler-plugin
│   ├── compile
│   │   └── default-compile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   └── testCompile
│   └── default-testCompile
│   ├── createdFiles.lst
│   └── inputFiles.lst
├── pro02-maven-web
│   ├── META-INF
│   ├── WEB-INF
│   │   ├── classes
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── HelloServlet.class
│   │   ├── lib
│   │   │   └── pro01-maven-java-1.0-SNAPSHOT.jar
│   │   └── web.xml
│   └── index.jsp
├── pro02-maven-web.war
├── surefire-reports
│   ├── TEST-com.yukiyama.maven.CalculatorTest.xml
│   └── com.yukiyama.maven.CalculatorTest.txt
└── test-classes
└── com
└── yukiyama
└── maven
└── CalculatorTest.class

依赖

查看依赖

执行 mvn dependency:list 可查看当前项目的依赖包列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
yukiyama@yukiyama pro02-maven-web % mvn dependency:list
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ pro02-maven-web ---
[INFO]
[INFO] The following files have been resolved:
[INFO] org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] com.yukiyama.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] junit:junit:jar:4.12:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.166 s
[INFO] Finished at: 2022-09-24T14:55:51+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

也可以执行 mvn dependency:tree 以树形结构查看。树形结构可看出依赖包的传递过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yukiyama@yukiyama pro02-maven-web % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro02-maven-web ---
[INFO] com.yukiyama.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] \- com.yukiyama.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.126 s
[INFO] Finished at: 2022-09-24T14:57:02+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

依赖范围

<dependency> 标签下的 <scope> 标签表示该依赖的范围,即该依赖 (Jar) 包可以作用于哪些目录下 (的 Java 文件中),通俗地说就是哪些地方的 Java 文件能够引用该依赖 Jar 包中的类。常用的 scope 有 compile, test, provided。

scope main目录 test目录 开发过程 部署到服务器
compile 有效 有效 有效 有效
test 无效 有效 有效 无效
provided 有效 有效 有效 无效
  • compile:在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的,例如 SSM 框架所需 jar 包。compile 是默认的,可以不必在 dependency 中显式写出。

  • test:测试过程中使用的 jar 包,例如 junit。

  • provided:通常为开发过程中所需的「服务器上的 jar包」,例如 servlet-api、jsp-api。开发测试时需要,但由于服务器已提供,部署到服务器时不需要。这是为了避免和服务器已存在的同类 jar 包冲突, 同时减轻服务器的负担,因此 provided 的 jar 包部署,不会放入 war 包中。

测试在 main 下依赖 test 范围的 jar 包

在 main 中的 java 文件导入 junit,即加入 import org.junit.Test; ,然后执行 mvn compile ,报如下错误 (… package org.junit does not exist …)。说明 test 依赖范围的 Jar 包 (类) 不会作用于 main 目录下的 Java 文件。

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
yukiyama@yukiyama pro01-maven-java % mvn clean compile
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ pro01-maven-java ---
[INFO] Deleting /Users/yukiyama/maven/workspace/test/pro01-maven-java/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ pro01-maven-java ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ pro01-maven-java ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/yukiyama/maven/workspace/test/pro01-maven-java/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/main/java/com/yukiyama/maven/Calculator.java:[3,17] package org.junit does not exist
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.683 s
[INFO] Finished at: 2022-09-24T17:04:44+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project pro01-maven-java: Compilation failure
[ERROR] /Users/yukiyama/maven/workspace/test/pro01-maven-java/src/main/java/com/yukiyama/maven/Calculator.java:[3,17] package org.junit does not exist
[ERROR]
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
yukiyama@yukiyama pro01-maven-java %

测试 test 和 provided 范围不参与服务器部署

在前述 web 工程「再次打包」后,我们已经看到,在 /target/pro02-maven-web/WEB-INF/lib 下打包了 compile 范围的 pro01-maven-java-1.0-SNAPSHOT.jar ,但并未打包 test 范围的 junit 以及 provided 范围的 javax.servlet-api


依赖传递

A 依赖 B,B 依赖 C 时,A 是否自动依赖 C 取决于 B 依赖 C 时在 B 的 pom.xml 中定义的对 C 的依赖范围。该范围为 compile 时可以传递,为 test 或 privoided 时不能传递。不能传递而 A 又需要依赖 C 时,就必须在 A 的 pom.xml 中明确添加上 C 的 dependency 。

测试依赖传递

pro01-maven-java 工程的 pom.xml 中添加如下依赖 (默认 compile)。

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>

接着执行 mvn dependency:tree ,可以看到 junit 所依赖的 hamcrest 和 spring-core 所依赖的 commons-logging 被传递到了当前工程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yukiyama@yukiyama pro01-maven-java % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.yukiyama.maven:pro01-maven-java >-----------------
[INFO] Building pro01-maven-java 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro01-maven-java ---
[INFO] com.yukiyama.maven:pro01-maven-java:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.855 s
[INFO] Finished at: 2022-09-24T17:32:14+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro01-maven-java %

接着以 pro02-maven-web 为 A, pro01-maven-java 为 B 测试依赖传递。要先重新在 pro01-maven-java 下执行 mvn clean install 更新其在本地仓库中的包。然后再在 pro02-maven-web 中执行 mvn dependency:tree 查看依赖传递信息。可以看到在 pro01-maven-java (B) 下,传递了 compile 范围的 spring-core ,而未传递 B 中 test 范围的 junit 以及 provided 范围的 javax.servlet-api 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
yukiyama@yukiyama pro02-maven-web % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro02-maven-web ---
[INFO] com.yukiyama.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] \- com.yukiyama.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.601 s
[INFO] Finished at: 2022-09-24T18:13:42+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

依赖排除

有 A -> B -> Z 和 A -> C -> Z 依赖关系时,因为前者已经通过依赖传递依赖了 Z,为了避免 jar 包冲突,后者可以排除依赖,即可以在 A 的 pom.xml 中的 C 的 <dependency> 标签中使用 <exclusions> , <exclusion> 标签, 阻止 C 将 Z 传递到 A。

pro02-maven-web 的 pom.xml 文件对 pro01-maven-java 的依赖修改如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependency>
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 添加依赖排除 -->
<exclusions>
<exclusion>
<!-- 不需要写version -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>

</dependency>

可以看到 commons-logging 已被排除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
yukiyama@yukiyama pro02-maven-web % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.yukiyama.maven:pro02-maven-web >-----------------
[INFO] Building pro02-maven-web Maven Webapp 1.0-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro02-maven-web ---
[INFO] com.yukiyama.maven:pro02-maven-web:war:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.12:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] \- com.yukiyama.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile
[INFO] \- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.656 s
[INFO] Finished at: 2022-09-24T18:27:39+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro02-maven-web %

继承

描述工程之间的继承关系,即 B 工程继承 A 工程,配置表现为 A 工程的 pom.xml 中的 <packaging> 标签为 pom ,表示 A 工程是一个用于管理工程的工程,即父工程。而 B 工程的 pom.xml 文件中具有 <parent> 标签描述 A 工程,表示 B 工程为 A 工程的子工程。

工程的继承关系建立后,可在父工程中统一管理项目中的依赖信息 (主要指依赖的版本) 。一个复杂的工程的「工程层级」很多,良好的依赖的组合方案通过继承可以在创建新项目时复用,节约时间的同时保证项目依赖关系的准确性 (经过了实践的组合方案)。

首先创建一个名为 pro03-maven-parent 的 Maven java 工程,然后修改 pom.xml 中的打包方式为 pom。<dependencies> 标签可以删除。

1
2
3
4
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

接着在 pro03-maven-parent 目录下新建三个子工程。完成后父工程的 pom.xml 中新增了记录子工程信息的 <modules> 标签。

1
2
3
4
5
<modules>
<module>pro04-maven-module</module>
<module>pro05-maven-module</module>
<module>pro06-maven-module</module>
</modules>

而子工程的 pom.xml 中新增了 <parent> 标签记录其父工程。

1
2
3
4
5
<parent>
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

另外,若子工程坐标中的 groupId 和 version 与其父工程相同,可省略。

1
2
3
<!-- <groupId>com.yukiyama.maven</groupId> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->

现在,在父工程 pom.xml 中使用 <dependencyManager> 标签统一管理其子工程的依赖版本,如下。

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
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程,需要在子工程中添加需要的依赖,只是无需写版本号 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>

此时子工程不会自动依赖这些在父工程中依赖的包,而是按需在其自身的 pom.xml 中添加,但 不再需要维护版本信息,而是由父工程统一管理 。如在子工程 pro04-maven-module 的 pom.xml 中添加如下被版本管理的依赖。

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>

然后在该 pom.xml 所在路径下执行 mvn dependency:tree 查看依赖信息。可以看到 pro04-maven-module 依赖了 spring-core 和 spring-beans,且版本号为父工程 pom 中指定的 4.0.0 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yukiyama@yukiyama pro04-maven-module % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< com.yukiyama.maven:pro04-maven-module >----------------
[INFO] Building pro04-maven-module 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro04-maven-module ---
[INFO] com.yukiyama.maven:pro04-maven-module:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:4.0.0.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] +- org.springframework:spring-beans:jar:4.0.0.RELEASE:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.274 s
[INFO] Finished at: 2022-09-24T20:39:06+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro04-maven-module %

当我们需要统一修改子工程中的依赖版本时,只需要在父工程中完成修改。例如在父工程的 pom.xml 中将前述 spring-core 和 spring-beans 的版本修改为 4.1.0 并保存后。再次查看 pro04-maven-module 的依赖信息,可以看到依赖的版本信息随之更新了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
yukiyama@yukiyama pro04-maven-module % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< com.yukiyama.maven:pro04-maven-module >----------------
[INFO] Building pro04-maven-module 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/springframework/spring-core/4.1.0.RELEASE/spring-core-4.1.0.RELEASE.pom
...(略)...
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro04-maven-module ---
[INFO] com.yukiyama.maven:pro04-maven-module:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:4.1.0.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.3:compile
[INFO] +- org.springframework:spring-beans:jar:4.1.0.RELEASE:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 28.726 s
[INFO] Finished at: 2022-09-24T20:43:20+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro04-maven-module %

自定义标签

在 pom.xml 文件中,可在 <properties> 标签下设置 自定义标签 并引用。如下,将版本信息定义为 <yukiyama.spring.version> 标签,然后在需要用到的地方引用即可。统一引用之后,需要修改时只需要在自定义处修改,则引用该自定义标签的内容也都随之更新。

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
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 自定标签,方便引用,并实现一处修改,处处修改 -->
<yukiyama.spring.version>4.2.0.RELEASE</yukiyama.spring.version>
</properties>

<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程,需要在子工程中添加需要的依赖,但无需写版本号 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${yukiyama.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${yukiyama.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${yukiyama.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${yukiyama.spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${yukiyama.spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

再次查看子工程的依赖信息,可以看到版本号更新为了自定义标签中指定的 4.2.0 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
yukiyama@yukiyama pro04-maven-module % mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< com.yukiyama.maven:pro04-maven-module >----------------
[INFO] Building pro04-maven-module 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/springframework/spring-core/4.2.0.RELEASE/spring-core-4.2.0.RELEASE.pom
...(略)...
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ pro04-maven-module ---
[INFO] com.yukiyama.maven:pro04-maven-module:jar:1.0-SNAPSHOT
[INFO] +- org.springframework:spring-core:jar:4.2.0.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.2:compile
[INFO] +- org.springframework:spring-beans:jar:4.2.0.RELEASE:compile
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 40.608 s
[INFO] Finished at: 2022-09-24T20:54:00+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro04-maven-module %

聚合

聚合即在父工程或者说「总工程」下将各个子工程或者说「模块工程」汇聚起来。使得在总工程下可统一执行整体项目的构建。聚合配置的方式在「继承」中展示过,即在总工程的 pom.xml 下以 <modules> 标签汇聚子项目。下面展示如何通过汇聚,由总工程完成包括子工程在内的整体项目构建。

pro04-maven-module 的 pom.xml 中添加对 pro05-maven-module 的依赖。

1
2
3
4
5
<dependency>
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro05-maven-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

pro05-maven-module 的 pom.xml 中添加对 pro06-maven-module 的依赖。

1
2
3
4
5
<dependency>
<groupId>com.yukiyama.maven</groupId>
<artifactId>pro06-maven-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

然后在「总工程」 pom.xml 所在路径下执行 mvn clean install 命令,可以看到 install 的顺序是 pro03 > pro06 > pro05 > pro04 。

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
yukiyama@yukiyama pro03-maven-parent % mvn clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] pro03-maven-parent [pom]
[INFO] pro06-maven-module [jar]
[INFO] pro05-maven-module [jar]
[INFO] pro04-maven-module [jar]
[INFO]
[INFO] ---------------< com.yukiyama.maven:pro03-maven-parent >----------------
[INFO] Building pro03-maven-parent 1.0-SNAPSHOT [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ pro03-maven-parent ---
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ pro03-maven-parent ---
[INFO] Installing /Users/yukiyama/maven/workspace/test/pro03-maven-parent/pom.xml to /Users/yukiyama/maven/repo/com/yukiyama/maven/pro03-maven-parent/1.0-SNAPSHOT/pro03-maven-parent-1.0-SNAPSHOT.pom
...(略,依次安装 pro06, pro05 和 pro04)...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for pro03-maven-parent 1.0-SNAPSHOT:
[INFO]
[INFO] pro03-maven-parent ................................. SUCCESS [ 0.443 s]
[INFO] pro06-maven-module ................................. SUCCESS [ 7.294 s]
[INFO] pro05-maven-module ................................. SUCCESS [ 0.628 s]
[INFO] pro04-maven-module ................................. SUCCESS [ 0.783 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.334 s
[INFO] Finished at: 2022-09-24T21:16:59+08:00
[INFO] ------------------------------------------------------------------------
yukiyama@yukiyama pro03-maven-parent%

安装后 pro03-maven-parent 下的目录结构如下。

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
pro03-maven-parent
├── pom.xml
├── pro04-maven-module
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   └── java
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── App.java
│   │   └── test
│   │   └── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── AppTest.java
│   └── target
│   ├── classes
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── App.class
│   ├── generated-sources
│   │   └── annotations
│   ├── generated-test-sources
│   │   └── test-annotations
│   ├── maven-archiver
│   │   └── pom.properties
│   ├── maven-status
│   │   └── maven-compiler-plugin
│   │   ├── compile
│   │   │   └── default-compile
│   │   │   ├── createdFiles.lst
│   │   │   └── inputFiles.lst
│   │   └── testCompile
│   │   └── default-testCompile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   ├── pro04-maven-module-1.0-SNAPSHOT.jar
│   ├── surefire-reports
│   │   ├── TEST-com.yukiyama.maven.AppTest.xml
│   │   └── com.yukiyama.maven.AppTest.txt
│   └── test-classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── AppTest.class
├── pro05-maven-module
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   └── java
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── App.java
│   │   └── test
│   │   └── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── AppTest.java
│   └── target
│   ├── classes
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── App.class
│   ├── generated-sources
│   │   └── annotations
│   ├── generated-test-sources
│   │   └── test-annotations
│   ├── maven-archiver
│   │   └── pom.properties
│   ├── maven-status
│   │   └── maven-compiler-plugin
│   │   ├── compile
│   │   │   └── default-compile
│   │   │   ├── createdFiles.lst
│   │   │   └── inputFiles.lst
│   │   └── testCompile
│   │   └── default-testCompile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   ├── pro05-maven-module-1.0-SNAPSHOT.jar
│   ├── surefire-reports
│   │   ├── TEST-com.yukiyama.maven.AppTest.xml
│   │   └── com.yukiyama.maven.AppTest.txt
│   └── test-classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── AppTest.class
├── pro06-maven-module
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   └── java
│   │   │   └── com
│   │   │   └── yukiyama
│   │   │   └── maven
│   │   │   └── App.java
│   │   └── test
│   │   └── java
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── AppTest.java
│   └── target
│   ├── classes
│   │   └── com
│   │   └── yukiyama
│   │   └── maven
│   │   └── App.class
│   ├── generated-sources
│   │   └── annotations
│   ├── generated-test-sources
│   │   └── test-annotations
│   ├── maven-archiver
│   │   └── pom.properties
│   ├── maven-status
│   │   └── maven-compiler-plugin
│   │   ├── compile
│   │   │   └── default-compile
│   │   │   ├── createdFiles.lst
│   │   │   └── inputFiles.lst
│   │   └── testCompile
│   │   └── default-testCompile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   ├── pro06-maven-module-1.0-SNAPSHOT.jar
│   ├── surefire-reports
│   │   ├── TEST-com.yukiyama.maven.AppTest.xml
│   │   └── com.yukiyama.maven.AppTest.txt
│   └── test-classes
│   └── com
│   └── yukiyama
│   └── maven
│   └── AppTest.class
└── src
├── main
│   └── java
│   └── com
│   └── yukiyama
│   └── maven
│   └── App.java
└── test
└── java
└── com
└── yukiyama
└── maven
└── AppTest.java

110 directories, 42 files

工程间依赖时,要注意避免循环依赖,例如 pro03 > pro04 > pro05 > pro06 > pro04 。


IDE方式(idea)

使用 IntelliJ IDEA 2022.2.1 (Ultimate Edition) 演示。


设置

idea 本身已自带 maven ,但若想使用自己下载的 maven 版本,可以通过 File > New Projects Setup > Preferences for New Projects 菜单自定义 maven 相关信息,如下。

idea-global-maven-setting


创建项目

创建父项目

接着 File > Project ,选择 Maven Archetype,根据需要选择相应的 archetype ,设置坐标后完成创建。如下创建一个 Java 工程 (quickstart) ,工程名为 maven_in_action 。该工程将作为后续演示中三个 module 的父工程。

image-20221001120248093

创建后在 idea 中项目结构如下,与之前用命令行创建的 Java 项目类似。如不需要自动创建的 App.javaAppTest.java 文件,可删除。点击右侧的 maven 页签,可看到该页签集成了 maven 功能,十分方便操作。

maven_project_created

此时 maven_in_action 的打包方式为 jar ,可以手动修改为 pom 使其成为一个父工程,也可以直接在该工程下创建新的 module ,则 maven_in_action 会被 idea 自动修改为父工程。


创建子Java工程

通过 File > New > Module 菜单可创建子工程,如下,Archetype 选择 quickstart, 创建名为 pro01-module-java 的 java 子工程。

new-module

module-created

创建后,父工程 maven_in_actionpom.xml 文件被 idea 自动修改,多出 <modules> 标签,且 <packaging> 方式变为 pom

1
2
3
4
<modules>
<module>pro01-module-java</module>
</modules>
<packaging>pom</packaging>

相比一般工程,子工程的 pom.xml 中具有 <parent> 标签,记录父工程的坐标信息。

1
2
3
4
5
<parent>
<artifactId>maven_in_action</artifactId>
<groupId>com.yukiyama.maven</groupId>
<version>1.0-SNAPSHOT</version>
</parent>

为方便后续演示,接着再创建一个子 Java 工程 pro02-module-java ,过程略。


创建子web工程

通过 File > New > Module 菜单可创建子工程,如下,Archetype 选择 webapp, 创建名为 pro03-module-web 的 web 子工程。

module-created

如下,可以看到父工程的 pom.xml<modules> 标签下记录了三个子工程的 artifactId (聚合),pro03-module-web 子工程打包方式为 war ,且其 <parent> 标签记录了父工程的坐标信息。

如下是自动创建的 web.xml 文件。

1
2
3
4
5
6
7
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

如下是自动创建的 index.jsp 文件。

1
2
3
4
5
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

如不需要自动创建的 web.xmlindex.jsp 文件,可删除。删除 web.xml 后,可通过 File > Project Structures > Project Settings > Modules,找到 web modules ,在右侧 Deployment Descriptors 中添加 web.xml ,填入正确路径 (WEB-INF 下),选择所需版本。然后再添加 Web Resources Directories (即 webapp) 。

新建 web.xml 的路径要确保为工程目录下的 src/main/webapp/WEB-INF/web.xml 。

Web Resource Directories 的路径要确保为工程目录下的 src/main/webapp 。

通过该方式新建的 web.xml 文件如下。可以看到使用该方式创建 web.xml 的优点时可以指定具体的版本,如下是 4.0 版本。

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
</web-app>

项目构建

在 idea 中,点击右侧 maven 页签打开maven操作界面,可以通过具体工程下的 Lifecycle 或者 Plugins ,对该工程执行具体的 maven 命令。

如下,双击 pro01-module-java 的 Lifecycle 下的 test ,相当于对该工程执行 mvn test 命令。

也可以在 Maven 视窗中点击命令行工具图标 (Execute maven goal) ,在弹出的 Run Anything 界面右上角选择要执行的项目对象,中输入组合命令 (例如 mvn clean test 等) 后回车即可执行。

还可以选中 pom.xml ,右键 Open in > Terminal 的方式,在 idea 中以命令行形式执行 maven 命令,该方式与在终端工具中输入具体命令的方式一样,只不过是在 idea 中而不是 terminal 中执行命令。