配置环境变量

  1. 在环境变量设置MAVEN_HOME,值为Maven的安装路径
  2. path添加%MAVEN_HOME%\bin
  3. 在命令行输入mvn -v,出现版本号即配置成功

Maven配置文件

setting.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
45
46
47
48
49
50
51
52
53
54
55
56
  <!-- 配置本地仓库地址 -->
<localRepository>E:\LocalRepository</localRepository>

<!-- 配置国内镜像原 -->
<mirrors>

<!-- 阿里云镜像仓库 -->
<mirror>
<id>aliyun</id>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>*</mirrorOf>
</mirror>

<!-- 华为云镜像 -->
<mirror>
<id>huaweicloud</id>
<name>Huawei Maven Mirror</name>
<url>https://mirrors.huaweicloud.com/repository/maven/</url>
<mirrorOf>*</mirrorOf>
</mirror>

<!-- 腾讯云镜像 -->
<mirror>
<id>tencentcloud</id>
<name>TencentCloud Maven Mirror</name>
<url>https://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
<mirrorOf>*</mirrorOf>
</mirror>

<!-- 清华大学镜像 -->
<mirror>
<id>tsinghua</id>
<name>Tsinghua Maven Mirror</name>
<url>https://mirror.tuna.tsinghua.edu.cn/repository/maven/</url>
<mirrorOf>*</mirrorOf>
</mirror>

</mirrors>

<profiles>
<!-- java版本 -->
<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>
</profiles>

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
<!-- 当前Maven工程的坐标 -->
<groupId>com.xiaofei.maven</groupId>
<!-- 项目名称 -->
<artifactId>pro01-maven-java</artifactId>
<!-- 项目版本 -->
<version>1.0</version>

<!-- 当前Maven工程的打包方式,可选值有下面三种: -->
<!-- jar:表示这个工程是一个Java工程 -->
<!-- war:表示这个工程是一个Web工程 -->
<!-- pom:表示这个工程是“管理其他工程”的工程 -->
<packaging>jar</packaging>

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

<properties>
<!-- 工程构建过程中读取源码时使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- 当前工程所依赖的jar包 -->
<dependencies>
<!-- 使用dependency配置一个具体的依赖 -->
<dependency>

<!-- 在dependency标签内使用具体的坐标依赖我们需要的一个jar包 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>

<!-- scope标签配置依赖的范围 -->
<scope>test</scope>
</dependency>
</dependencies>

Maven普通目录结构

./images

Maven构建命令

要求

运行 Maven 中和构建操作相关的命令时,必须进入到 pom.xml 所在的目录。

mvn -v 命令和构建操作无关,只要正确配置了 PATH,在任何目录下执行都可以。而构建相关的命令要在 pom.xml 所在目录下运行——操作哪个工程,就进入这个工程的 pom.xml 目录。

清理操作

mvn clean

效果:删除 target 目录

编译操作

主程序编译:mvn compile

测试程序编译:mvn test-compile

主体程序编译结果存放的目录:target/classes

测试程序编译结果存放的目录:target/test-classes

测试操作

mvn test

测试的报告存放的目录:target/surefire-reports

打包操作

mvn package

打包的结果——jar 包,存放的目录:target

安装操作

mvn install

安装的效果是将本地构建过程中生成的 jar 包存入 Maven 本地仓库。这个 jar 包在 Maven 仓库中的路径是根据它的坐标生成的。

Maven创建Web项目

1
mvn archetype:generate -D archetypeGroupId=org.apache.maven.archetypes -D archetypeArtifactId=maven-archetype-webapp -D archetypeVersion=1.4

确认打包方式

1
<packaging>war</packaging>

创建一个servlet所需API

下载网站:https://mvnrepository.com/

pom标签解读

scope

标签位置:dependencys/dependency/scope

标签可选值:compile / test / provided / system / runtime / import

默认的标签值为compile

compile 和 test 对比

main目录(空间) test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
test 无效 有效 有效 无效

compile 和 provided 对比

main目录(空间) test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
provided 有效 有效 有效 无效

结论

  • compile:通常使用的第三方框架的 jar 包这样在项目实际运行时真正要用到的 jar 包都是以 compile 范围进行依赖的。比如 SSM 框架所需jar包。、
  • test:测试过程中使用的 jar 包,以 test 范围依赖进来。比如 junit。
  • provided:在开发过程中需要用到的“服务器上的 jar 包”通常以 provided 范围依赖进来。比如 servlet-api、jsp-api。而这个范围的 jar 包之所以不参与部署、不放进 war 包,就是避免和服务器上已有的同类 jar 包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”

依赖传递性

概念

A 依赖 B,B 依赖 C,那么在 A 没有配置对 C 的依赖的情况下,A 里面能不能直接使用 C?

传递原则

在 A 依赖 B,B 依赖 C 的前提下,C 是否能够传递到 A,取决于 B 依赖 C 时使用的依赖范围。

  • B 依赖 C 时使用 compile 范围:可以传递
  • B 依赖 C 时使用 test 或 provided 范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。

test和provided不能传递

exclusions

当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>com.xiaofei.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

继承

创建父工程

创建简单的maven项目,将项目的打包方式修改为pom,其余文件删除,子工程放在该父工程的下面

image-20220609111004022

父工程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
<?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.xiaofei.pom</groupId>
<artifactId>maven-pom</artifactId>
<version>1.0</version>

<!--将打包方式改为pom,标注该项目是一个父工程-->
<packaging>pom</packaging>

<!-- 将依赖于该父工程的模块加入modules标签中 -->
<modules>
<module>child</module>
</modules>

<!-- 同一指定版本号 -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!--自定义标签,设置版本号,在下面直接使用${junit-version}引入即可-->
<!--该标签在子子工程中也可使用-->
<junit-version>4.12</junit-version>
</properties>

<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程 -->
<dependencyManagement>
<dependencies>
<!-- 管理项目版本 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- 在上面的properties标签中已经指定了版本号,这里直接使用${}标签引入版本号即可 -->
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

</project>

子工程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
<?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">

<!-- 使用parent标签指定当前工程的父工程 -->
<parent>
<artifactId>maven-pom</artifactId>
<groupId>com.xiaofei.pom</groupId>
<version>1.0</version>
</parent>

<modelVersion>4.0.0</modelVersion>

<!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.xiaofei.pom</groupId> -->
<artifactId>child</artifactId>
<!-- <version>1.0</version> -->

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
<!-- 引入的父工程中已经将junit的版本锁定,所以,子工程中可以不需要设置版本号 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!--子工程也可使用父工程中定义的${junit-version}自定义标签-->
<!-- <version>${junit-version}</version> -->
<scope>test</scope>
</dependency>
</dependencies>

</project>

实际意义

编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。

如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。

./images

聚合

  • 聚合意义

    部分组成整体

  • Maven 中的聚合

    使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。‘

  • 好处

    一键执行 Maven 命令:很多构建命令都可以在“总工程”中一键执行。

    以 mvn install 命令为例:Maven 要求有父工程时先安装父工程;有依赖的工程时,先安装被依赖的工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行。

    配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。

依赖循环问题

如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报下面的错误:

Maven本地仓库清理

1
2
3
4
5
6
7
8
9
@echo off

rem 指定要查询的文件夹路径
set "search_dir=E:\LocalRepository"

rem 删除所有_remote.repositories文件
del /s /q "%search_dir%\_remote.repositories"
del /s /q "%search_dir%\*lastUpdated*"
del /s /q "%search_dir%\*sha1*"

Maven生命周期

作用:为了让构建过程自动化完成,Maven 设定了三个生命周期,生命周期中的每一个环节对应构建过程中的一个操作。

笔记

http://heavy_code_industry.gitee.io/code_heavy_industry/