Maven使用手册¶
1 下载maven¶
进入官网下载需要的版本:Maven - 下载Apache Maven
2 安装maven¶
将下载的压缩包解压到非中文、没有空格的目录,在解压目录中,我们需要着重关注 Maven
的核心配置文件: conf/settings.xml
3 创建本地仓库¶
本地仓库这个目录,我们手动创建一个空的目录即可。
4 指定本地仓库¶
本地仓库默认值:用户家目录 /.m2/repository
。由于本地仓库的默认位置是在用户的家目录下,而家目录往往是在 C盘
,也就是系统盘。将来 Maven
仓库中 jar
包越来越多,仓库体积越来越大,可能会拖慢 C盘
运行速度,影响系统性能。所以建议将 Maven
的本地仓库放在其他盘符下。
配置方式如下:
打开 maven
里的 conf
文件,打开 setings.xml
文件,配置本地仓库文件
XML | |
---|---|
1 2 3 4 5 6 7 8 |
|
Tip
记住:一定要把 localRepository
标签从注释中拿出来。
注意:本地仓库本身也需要使用一个非中文、没有空格的目录。
5 配置阿里云提供的镜像仓库¶
Tip
为什么要配置阿里云提供的镜像仓库?
Maven
下载 jar
包默认访问境外的中央仓库,速度很慢。改成阿里云提供的镜像仓库,访问国内网站,可以让 Maven
下载 jar
包的时候速度更快。
配置的方式是:
打开 maven
里的 conf
文件,打开 setings.xml
文件,
将下面 mirror
标签整体复制到 mirrors
标签的内部。
XML | |
---|---|
1 2 3 4 5 6 7 8 |
|
6 配置Maven工程的基础JDK版本¶
Tip
如果按照默认配置运行, Java
工程使用的 JDK
版本是 1.5
。
配置的方式是:
打开 maven
里的 conf
文件,打开 setings.xml
文件,
将 profile
标签整个复制到 profiles
标签内。
XML | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
7 配置环境变量¶
Tip
Maven
是一个用 Java
语言开发的程序,它必须基于 JDK
来运行,需要通过 JAVA_HOME
来找到 JDK
的安装位置。
可以使用下面的命令验证:
Bash | |
---|---|
1 2 3 4 5 6 |
|
8 配置MAVEN_HOME¶
配置环境变量的规律:
XXX_HOME
指向的是 bin
目录的上一级
PATH
指向的是 bin
目录
配置path:
验证:
Bash | |
---|---|
1 2 3 4 5 6 |
|
9 Maven的仓库和坐标¶
9.1 Maven的仓库¶
maven
的仓库就是 maven
存放 jar
包的位置,主要分为如下三类仓库
仓库名称 | 作用 |
---|---|
本地仓库 | 相当于缓存,工程第一次会从远程仓库(互联网)去下载 jar 包,将 jar 包存在本地仓库(在程序员的电脑上)。第二次不需要从远程仓库去下载。先从本地仓库找,如果找不到才会去远程仓库找。 |
中央仓库 | 仓库中 jar 由专业团队( maven 团队)统一维护。中央仓库的地址:https://repo1.maven.org/maven2/ |
远程仓库 | 在公司内部架设一台私服,其它公司架设一台仓库,对外公开。 |
9.2 Maven的坐标¶
Maven
的一个核心的作用就是管理项目的依赖,引入我们所需的各种 jar
包等。为了能自动化的解析任何一个 Java
构件, Maven
必须将这些 Jar
包或者其他资源进行唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标。包括我们自己开发的项目,也是要通过坐标进行唯一标识的,这样才能在其它项目中进行依赖引用。坐标的定义元素如下:
-
groupId
:项目组织唯一的标识符,实际对应JAVA
的包的结构(一般写公司的组织名称eg:com.itheima,com.alibaba
) -
artifactId
:项目的名称 -
version
:定义项目的当前版本
例如:要引入 druid
,只需要在 pom.xml
配置文件中配置引入 druid
的坐标即可:
XML | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
10 在IDEA中集成Maven¶
10.1 配置maven软件的安装路径和本地仓库路径¶
10.2 配置Maven的Runner参数¶
参数一: -DarchetypeCatalog=internal
解决使用骨架构建 Maven
项目时候会卡住的问题
参数二: -Dfile.encoding=GB2312
解决 Maven
工程中控制台输出中文乱码的问题
注意事项:
上述配置如果是在 settings
中进行配置则只会对当前 Project
生效,后续创建的新的 Project
不会生效
如果是在 New Projects Setup
里面的 setting for new projects
中配置,则会对后续创建的所有新的 Project
都生效,但是无法对当前项目生效
11 使用IDEA创建基于Maven的工程¶
使用 IDEA
创建基于 Maven
的工程有两种方式:
-
使用
Maven
骨架创建(不建议使用,因为构建速度慢,而且容易卡死) -
不使用
Maven
骨架创建(建议使用),我们以后创建Maven
工程就选择这种方式创建
11.1 创建JavaSE工程¶
-
第一步
-
第二步
创建后的工程目录
引入单元测试的依赖
XML | |
---|---|
1 2 3 4 5 6 7 |
|
11.2 创建JavaWeb工程¶
-
在
IDEA
中安装一个插件(JBLJavaToWeb
) -
按照创建
javase
工程的方式创建(此时创建出来的是javase
工程) -
使用
JBLJavaToWeb
插件将javase
工程转成javaweb
工程
转换之后会在 main
目录中多出一个 web
目录,并且 pom.xml
文件中会自动添加打包方式为 <packaging>war<packaging/>
因为我们需要在 javaweb
项目中使用 Servlet
,所以需要引入 Servlet
的依赖
XML | |
---|---|
1 2 3 4 5 6 |
|
12 Maven构建命令¶
执行 Maven
构建命令有两种方式:
-
如果是自己使用
IDEA
创建的Maven
工程,可以自己直接在IDEA
的Maven
面板上执行相应的构建命令 -
如果是该项目是从其它地方拷贝过来的,并且没有在
IDEA
上打开,则可以使用命令行来进行Maven
构建
注意事项:
运行 Maven
中和构建操作相关的命令时,必须进入到 pom.xml
所在的目录。如果没有在 pom.xml
所在的目录运行 Maven
的构建命令,那么会看到下面的错误信息:
Bash | |
---|---|
1 |
|
12.1 清理程序¶
mvn clean
命令是清除项目的编译内容,具体的效果是删除 target
目录
12.2 编译程序¶
compile
命令是对工程进行编译,具体效果是产生 target
目录,而编译又分为:编译主程序和编译测试程序
12.2.1 编译主程序¶
mvn compile
命令是编译主程序,主程序编译之后的文件会生成在 target/classes
目录中
12.2.2 编译测试程序¶
mvn test-compile
命令是编译测试程序,测试程序编译之后的文件会生成在 target/test-classes
目录中
12.3 执行测试¶
mvn test
会执行测试程序中的所有测试用例,并且将生成的测试报告存放在 target/surefire-reports
目录下。
在执行 mvn test
命令的过程中,会自动先执行 mvn clean
、 mvn compile
、 mvn test-compile
,然后再执行 mvn test
进行测试
12.4 程序打包¶
mvn package
命令会对程序进行打包,如果是 javase
工程会打成 jar
包,而 javaweb
工程则会打成 war
包,打包得到的结果会生成在 target
目录中
在执行 mvn package
命令的过程中,会自动先执行 mvn clean
、 mvn compile
、 mvn test-compile
、 mvn test
,然后再执行 mvn package
进行打包
12.5 安装操作¶
mvn install
命令会将程序打成的包安装到本地仓库(针对 jar
包, war
包安装到本地仓库意义不大)
在执行 mvn install
命令的过程中,会自动先执行 mvn clean
、 mvn compile
、 mvn test-compile
、 mvn test
、 mvn package
,然后再执行 mvn package
进行打包
安装的效果是将本地构建过程中生成的 jar
包存入 Maven
本地仓库。这个 jar
包在 Maven
仓库中的路径是根据它的坐标生成的。
坐标信息如下:
XML | |
---|---|
1 2 3 |
|
在 Maven
仓库中生成的路径如下:
Bash | |
---|---|
1 |
|
另外,安装操作还会将 pom.xml
文件转换为 XXX.pom
文件一起存入本地仓库。所以我们在 Maven
的本地仓库中想看一个 jar
包原始的 pom.xml
文件时,查看对应 XXX.pom
文件即可,它们是名字发生了改变,本质上是同一个文件。
13 Maven的依赖¶
13.1 引入依赖¶
在 maven
项目中,我们只需要通过 jar
包的 maven
坐标去引入 jar
包就可以了,而不需要像之前一样手动导入 jar
包。至于每一个 jar
包的坐标到底怎么写,我们不需要记忆,写代码的时候可以直接复制,如果需要查找则可以到http://mvnrepository.com/网站查找即可
例如,引入单元测试的依赖:
XML | |
---|---|
1 2 3 4 5 6 7 8 |
|
当前项目的所有依赖都是放在 <dependencies>
标签里面,而具体每一个 jar
包的坐标则是放在一个 <dependency>
标签中
13.2 依赖范围¶
<scope>
标签表示依赖的范围,它的位置是在 dependencies/dependency/scope
,该标签中的值可以是 compile
、 test
、 provided
、 runtime
这四个值中的一个,如果没有手动指定依赖范围,那么依赖范围默认是 compile
13.3 四种依赖范围的对比¶
依赖范围 | main目录(空间) | test目录(空间) | 编译阶段(时间) | 运行阶段(时间) |
---|---|---|---|---|
compile | 有效 | 有效 | 有效 | 有效 |
test | 无效 | 有效 | 有效 | 无效 |
provided | 有效 | 有效 | 有效 | 无效 |
runtime | 无效 | 无效 | 无效 | 有效 |
-
compile
:该范围的依赖既可以在main
目录使用,又可以在test
目录使用,即在编译阶段使用,又在实际运行阶段使用(会打到war/jar
包中),通常使用的第三方框架的jar
包这样在项目实际运行时真正要用到的jar
包都是以compile
范围进行依赖的。比如SSM
框架所需jar
包。 -
test
:该范围的依赖只能在test
目录中使用,不能在main
目录中使用,只能在编译阶段使用,无法在项目运行阶段使用(不会打到war/jar
包中),引入junit
单元测试依赖的时候会使用该范围 -
provided
:该范围的依赖即可在main
目录使用,又可以在test
目录使用,但是它只能在编译阶段使用,无法在项目运行阶段使用(不会打到war/jar
包中)。比如说Tomcat
服务器中内置有servlet-api
、jsp-api
等等依赖,所以我们在项目中引入这些依赖的时候的目标仅仅是让我们的代码编译通过,为了避免和服务器上已有的同类jar
包产生冲突,同时减轻服务器的负担我们不会选择将这些依赖打到war
包中。说白了就是:“服务器上已经有了,你就别带啦!” -
runtime
:该范围的依赖既不可在main
目录使用,又不可在test
目录使用,说白了就是它无法在编译阶段使用,只能在项目运行阶段使用(会打到war/jar
包中)。比如说MySQL
驱动的依赖,我们在开发(写代码)的过程中根本不需要使用MySQL
驱动中的任何类(因为都是直接用的JDBC
接口),只在运行阶段需要MySQL
驱动的依赖,所以我们就可以将MySQL
驱动的范围指定为runtime
这样能有助于提升编译效率
13.4 依赖的传递性和依赖的排除¶
13.4.1 依赖的传递性¶
依赖的传递性指的是: A
依赖 B
, B
依赖 C
,那么在 A
没有配置对 C
的依赖的情况下, A
里面能不能直接使用 C
。在 A
依赖 B
, B
依赖 C
的前提下, C
是否能够传递到 A
,取决于 B
依赖 C
时使用的依赖范围。
-
B
依赖C
时使用compile
范围:可以传递 -
B
依赖C
时使用test
或provided
范围:不能传递,所以需要这样的jar
包时,就必须在需要的地方明确配置依赖才可以。
13.4.2 依赖的排除¶
13.4.2.1 什么是依赖排除¶
当 A
依赖 B
, B
依赖 C
而且 C
可以传递到 A
的时候,但是 A
不想要 C
,需要在 A
里面把 C
排除掉。而往往这种情况都是为了避免 jar
包之间的冲突。
所以配置依赖的排除其实就是阻止某些 jar
包的传递。因为这样的 jar
包传递过来会和其他 jar
包冲突。
13.4.2.2 怎么实现依赖排除¶
XML | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
14 继承和聚合¶
14.1 继承¶
14.1.1 概念¶
Maven
工程之间, A
工程继承 B
工程
-
B
工程:父工程 -
A
工程:子工程
本质上是 A
工程的 pom.xml
中的配置继承了 B
工程中 pom.xml
的配置。
14.1.2 作用¶
在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本,各个子工程使用依赖的时候版本就统一了
14.1.3 配置¶
在子工程的 pom.xml
文件中通过 <parent>
标签指定当前子工程的父工程
XML | |
---|---|
1 2 3 4 5 |
|
14.1.4 继承的实际意义¶
编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。
如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。
14.2 聚合¶
14.2.1 概念¶
使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。
-
项目:整体
-
模块:部分
从继承关系角度来看:
-
父工程
-
子工程
从聚合关系角度来看:
-
总工程
-
模块工程
14.2.2 作用¶
-
一键执行
Maven
命令:很多构建命令都可以在“总工程”中一键执行。以mvn install
命令为例:Maven
要求有父工程时先安装父工程;有依赖的工程时,先安装依赖的工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行mvn install
可以一键完成安装,而且会自动按照正确的顺序执行。 -
配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。
14.2.3 配置¶
14.2.3.1 在总工程的pom.xml中指定总工程的打包方式为pom¶
XML | |
---|---|
1 2 3 4 |
|
14.2.3.2 在总工程的pom.xml中指定总工程需要聚合的所有分工程¶
XML | |
---|---|
1 2 3 4 5 |
|
14.2.3.3 项目聚合需要注意循环依赖的问题¶
如果 A
工程依赖 B
工程, B
工程依赖 C
工程, C
工程又反过来依赖 A
工程,那么在执行构建操作时会报下面的错误:
Bash | |
---|---|
1 |
|
这个错误的含义是:循环引用。
14.3 继承和聚合的具体操作¶
14.3.1 创建父工程¶
使用 maven
创建 javase
工程的方式创建父工程
因为父工程中只需要管理项目依赖的版本,不用编写 java
,所以可以删除父工程的src目录,只保留 pom.xml
文件
注意:在父工程的 pom.xml
中需要指定打包方式为 pom
XML | |
---|---|
1 2 3 4 |
|
14.3.2 在父工程中统一管理项目所需的所有依赖的版本¶
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 |
|
14.3.3 创建多个子工程¶
因为需要将子工程创建在父工程下,所以注意要将子工程的路径指定在父工程路径下
所有子工程都创建好之后的项目结构:
观察子工程的 pom.xml
文件可以看到, pom.xml
文件中自动生成了 <parent>
标签用于指定父工程
XML | |
---|---|
1 2 3 4 5 |
|
观察父工程的 pom.xml
文件可以看到, pom.xml
文件中自动生成了 <modules>
标签用于指定父工程聚合的所有子工程
XML | |
---|---|
1 2 3 4 5 |
|
14.3.4 在子工程中引入依赖¶
因为父工程中已经统一管理了所有依赖的版本,所以子工程引入依赖的时候就不需要写依赖的版本了
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 |
|
虽然在子工程中引入依赖的时候没有写依赖的版本,但我们可以看到子工程中实际引入的依赖的版本和父工程中统一管理的版本是一致的
14.4.5 在父工程中自定义属性进行版本锁定¶
14.4.5.1 什么是自定义属性¶
在 pom.xml
文件中的 <properties>
标签中添加子标签进行自定义属性,子标签的标签名就是属性名,子标签的标签体的内容就是属性值,例如:
XML | |
---|---|
1 2 3 |
|
那么我们在 pom.xml
中就可以使用 ${属性名}
来获取属性值
14.4.5.2 什么是版本锁定¶
因为父工程在管理项目依赖的时候,需要管理非常多的依赖,而有很多依赖的版本都应该是相同的,比如 spring
框架的相关依赖都需要统一版本
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 |
|
如果未进行版本锁定的话,我们修改 spring
框架的版本的时候,就需要手动将每一个依赖的版本都进行修改,这无疑是非常麻烦而且容易出错的操作
所谓版本锁定就是自定义一个属性,属性值就是要统一的版本,然后在 <version>
标签体中引入该属性值就行了
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 |
|
15 jar包下载失败问题的解决方案¶
15.1 为什么会发生jar包下载失败¶
Maven
替我们去下载 jar
包的时候,有可能出现在网络传输过程中数据丢失、中途断网,从而导致下载失败。
15.2 Maven正常下载的做法¶
-
jar
包在下载过程中,jar
包的扩展名是xxx.jar.lastUpdated
-
jar
包下载成功后,Maven
会将lastUpdated
扩展名删除,让jar
包恢复为xxx.jar
这样的名称
15.3 下载失败的第一种情况¶
15.3.1 Maven的行为描述¶
-
jar
包在下载过程中,jar
包的扩展名是xxx.jar.lastUpdated
-
网络连接丢失,无法继续下载
-
jar
包没有下载完,lastUpdated
扩展名不会被删除 -
当我们要求
Maven
重新下载时,Maven
看到这个jar
包的扩展名是lastUpdated
,Maven
就不会重新下载了
15.3.2 解决办法¶
手动删除所有以 lastUpdated
结尾的文件,然后让 Maven
重新下载。可是当仓库中 lastUpdated
文件太多的时候,手动删除不可行,所以我们需要借助批处理文件: clearLastUpdated.bat
。
代码:
Bash | |
---|---|
1 2 3 4 5 6 7 |
|
使用方法:
-
将
clearLastUpdated.bat
文件复制到本地仓库的根目录 -
使用文件编辑打开
clearLastUpdated.bat
文件 -
修改下面的内容
Bash 1
SET CLEAR_PATH=设置为本地仓库所在的盘符 SET CLEAR_DIR=设置为本地仓库的根目录的路径
例如:
Bash 1
SET CLEAR_PATH=D: SET CLEAR_DIR=D:\maven-rep1026
-
在想要执行清理时,双击运行这个文件即可
15.3.3 要求Maven重新下载jar包¶
15.4 下载失败的第二种情况¶
15.4.1 文件校验工具¶
jar
包表面上看起来是下载完的状态,结尾并没有 .lastUpdated
扩展名。但是程序运行时找不到这个 jar
包中的类。例如:针对 jar
包中的类出现 ClassNotFoundException
。
遇到类似问题需要先确认一下“有嫌疑”的 jar
包是否存在内部损坏问题。此时可以使用上面的文件校验工具。
15.4.2 用法¶
-
打开文件校验工具
-
将待校验的
jar
包拖拽到文件校验工具窗口内 -
将待校验的
jar
包旁边的*.sha1
文件打开 -
比较两个
SHA1
值 -
一致:
jar
包完好 -
不一致:
jar
包损坏
15.4.3 原理¶
HASH
加密包括很多具体加密算法,但是所有 HASH
算法都满足下面特征:
-
只要输入数据不变,任何时候执行加密,输出不变
-
输入数据有细微变化,输出数据跟着变化
-
不可逆,不能通过密文反推回明文
-
每一种具体的HASH加密算法加密后长度固定
15.4.4 怎么快速找到有嫌疑的jar包¶
假设现在出现了一个 ClassNotFoundException
,提示找不到类: org.springframework.expression.Expression
。此时我们怀疑这个类所在的 jar
包下载失败。
-
窍门1
:类所在的package
命名往往和jar
包坐标的groupId
部分类似。 -
窍门2
:在IDEA
中按两下Shift
键,使用全类名搜索