第一章 前言
在目前的项目构建中,可以说不使用maven的情况基本不存在。今天把maven的基本概念以及使用总结了下,供大家以后作为入门和查询使用。
第二章 正文
2.1.Maven概念
Maven作为一个构建工具:
帮助我们自动化构建,我们只需关注命令即可。
抽象构建过程,提供构建任务实现。
跨平台,提供对外一致的操作接口。
Maven作为一个依赖管理工具和项目管理工具:
借助坐标系统准确定位每一个构件(artifact),有序管理依赖,轻松解决复杂依赖问题。
帮助管理项目中各个角落信息,如:项目描述、开发者列表、版本控制等。
提供全世界免费的中央仓库。
对于项目结构、测试用例命名方式等都有既定的规则,免去学习的成本,约定大于配置。
以上是对maven作用的总结,如果想具体了解这些作用的具体解释,传送门:https://www.tianmaying.com/tutorial/maven-basic
2.2.Maven的安装
2.2.1.Window安装
安装jdk,这个就不多说了。
下载你想要的Maven版本。传送门: http://maven.apache.org/download.cgi
系统配置环境变量。
验证是否安装成功。mvn -v
2.2.2.Linux安装
传送门:https://www.cnblogs.com/freeweb/p/5241013.html
2.3.Maven目录
bin目录:该目录包含了mvn运行的脚本,这些脚本用来配置java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。
boot目录:该目录只包含一个文件,该文件为plexus-classworlds-2.5.2.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更加丰富的语法以方便配置,Maven使用该框架加载自己的类库。
conf目录:该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为,一般情况下,我们更偏向于复制该文件至/.m2/目录下(表示用户目录),然后修改该文件,在用户范围定制Maven的行为。
lib目录:该目录包含了所有Maven运行时需要的Java类库,Maven本身是分模块开发的,因此用户能看到诸如maven-core-3.0.jar、maven-model-3.0.jar之类的文件,此外这里还包含一些Maven用到的第三方依赖如commons-cli-1.2.jar、commons-lang-2.6.jar等等。
2.3.1.Setting.xml文件
这里只讲下我们平常中使用比较多的参数属性。
1.localRepository:自定义本地库路径,默认在 ${user.home}/.m2中;
2.Servers:配置服务器需要的信息
3.Mirrors:为仓库列表配置的镜像。
如果想了解其他参数的作用,传送门:
https://www.cnblogs.com/shangguan/p/4829706.html
2.4.Maven插件
Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成。
2.4.1.核心插件
2.4.1.1.单个命令
Mvn compile:编译命令,该命令会将main目录中的源码进行编译,执行后在hellomaven下多一个target文件夹,仓库中也多了相关jar包等资源。
Mvn clean:清除命令,清除已经编译好的class文件,具体说清除的是target目录中的文件,包括target。仓库不清空
Mvn test:测试命令,该命令会将test和main目录中的源码进行编译,也会生成target等。并且会在【target\surefire-reports】中生成.txt文件报告执行情况(错误)。
Mvn package:打包命令,即将该程序打包为jar。在target目录下。
Mvn install:安装命令,会将打好的包,安装到本地仓库。生成的版本号等信息就是pom.xml文件配置的(引用):
2.4.1.2.组合命令
mvn -version:查看maven的版本及配置信息
mvn clean:表示运行清理操作(会默认把target文件夹中的数据清理)
mvn clean compile:表示先运行清理之后运行编译,会将代码编译到target文件夹中。
mvn clean test:运行清理和测试。
mvn clean package:运行清理和打包。
mvn clean install:运行清理和安装,会将打好的包安装到本地仓库中,以便其他的项目可以调用。
mvn clean deploy:运行清理和发布(发布到私服上面)。
mvn package -Dmaven.test.skip=true:打包项目时跳过单元测试。
mvn clean package -p test:适用于项目多环境打包。
2.4.2.其他插件
由于插件过于众多,这里只举例常用的插件。
2.4.2.1.编译插件
1.
2.
3.
4. org.apache.maven.plugins
5. maven-compiler-plugin
6.
7. 1.7
8. 1.7
9. UTF-8
10.
11.
12.
13.
即JDK:可以指定JDK的版本号
表示使用jdk_1.7。【修改后更新项目】
2.4.3.插件资源
Maven官方插件列表
http://maven.apache.org/plugins/index.html。
http://mojo.codehaus.org/plugins.html。
2.5.Maven集成到IDEA
2.6.Maven使用
1.<?xml version="1.0" encoding="UTF-8"?>
2.<project xmlns=“http://maven.apache.org/POM/4.0.0” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
3. xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
4. 4.0.0
5. com.tengj
6. springBootDemo1
7. 0.0.1-SNAPSHOT
8. springBootDemo1
9.
代码的第一行是XML头,指定了该xml文档的版本和编码方式。 project是所有pom.xml的根元素,它还声明了一些POM相关的命名空间及xsd元素。 根元素下的第一个子元素modelVersion指定了当前的POM模型的版本,对于Maven3来说,它只能是4.0.0 代码中最重要是包含了groupId,artifactId和version了。这三个元素定义了一个项目基本的坐标,在Maven的世界,任何的jar、pom或者jar都是以基于这些基本的坐标进行区分的。
groupId:定义了项目属于哪个组,随意命名,比如谷歌公司的myapp项目,就取名为 com.google.myapp
artifactId:定义了当前Maven项目在组中唯一的ID,比如定义hello-world。
version:指定了项目当前的版本0.0.1-SNAPSHOT,SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的。
name:元素生命了一个对于用户更为友好的项目名称,虽然这不是必须的,但还是推荐为每个POM声明name,以方便信息交流。
2.6.1.归类依赖
有时候我们引入的很多依赖包,他们都来自同一个项目的不同模块,所以他们的版本号都一样,这时候我们可以用属性来统一管理版本号。
1.
2. 4.0.0
3. com.juven.mvnbook.account
4. accout-email
5. 1.0.0-SNAPSHOT
6.
7. <springframework.version>1.5.6</springframework.version>
8.
9.
10.
11. org.springframework
12. spring-core
13.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
.
v
e
r
s
i
o
n
<
/
v
e
r
s
i
o
n
>
14.
<
/
d
e
p
e
n
d
e
n
c
y
>
15.
<
d
e
p
e
n
d
e
n
c
y
>
16.
<
g
r
o
u
p
I
d
>
o
r
g
.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
<
/
g
r
o
u
p
I
d
>
17.
<
a
r
t
i
f
a
c
t
I
d
>
s
p
r
i
n
g
−
b
e
a
n
s
<
/
a
r
t
i
f
a
c
t
I
d
>
18.
<
v
e
r
s
i
o
n
>
{springframework.version}</version> 14. </dependency> 15. <dependency> 16. <groupId>org.springframework</groupId> 17. <artifactId>spring-beans</artifactId> 18. <version>
springframework.version</version> 14. </dependency> 15. <dependency> 16. <groupId>org.springframework</groupId> 17. <artifactId>spring−beans</artifactId> 18. <version>{springframework.version}
19.
20.
21.
先通过
里定义你先要的版本复制代码
来定义,然后在下面依赖使用${}来引入你的属性。
2.6.2.传递依赖与排除依赖
传递依赖:如果我们的项目引用了一个Jar包,而该Jar包又引用了其他Jar包,那么在默认情况下项目编译时,Maven会把直接引用和简洁引用的Jar包都下载到本地。
排除依赖:如果我们只想下载直接引用的Jar包,那么需要在pom.xml中做如下配置:(将需要排除的Jar包的坐标写在中)
1.
2.
3. cn.missbe.web.search
4. resource-search
5. pom
6. 1.0-SNAPSHOT
7.
8.
2.6.3.依赖范围scope
在项目发布过程中,帮助决定哪些构件被包括进来。欲知详情请参考依赖机制。
Compile:默认范围,用于编译
Provided:类似于编译,但支持你期待jdk或者容器提供,类似于classpath
runtime:在执行时需要使用
test:用于test任务时使用
system:需要外在提供相应的元素。通过systemPath来取得
systemPath:仅用于范围为system。提供相应的路径
optional:当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用
2.6.4.依赖冲突
若项目中多个Jar同时引用了相同的Jar时,会产生依赖冲突,但Maven采用了两种避免冲突的策略,因此在Maven中是不存在依赖冲突的。
短路优先
本项目——>A.jar——>B.jar——>X.jar
本项目——>C.jar——>X.jar
若本项目引用了A.jar,A.jar又引用了B.jar,B.jar又引用了X.jar,并且C.jar也引用了X.jar。
在此时,Maven只会引用引用路径最短的Jar。
声明优先
若引用路径长度相同时,在pom.xml中谁先被声明,就使用谁。
2.6.5.优化依赖
在项目过程中,我们本需要依赖的一些jar包,可能通过传递依赖的形式依赖了,程序固然不会报错。但从长远来看,我们交接项目后,新人会对我们项目的依赖不够清晰。现在介绍2种方式去优化依赖。
2.6.5.1.命令形式
mvn dependency:tree
通过该命令,我们可以得到项目的依赖树。
对于我们需要声明但已经传递依赖过来,或者我们不需要却声明的依赖。有一个更方便的命令帮我们进行分析:
mvn dependency:analyze
Used undeclared dependencies found(用到却没有显示声明),我们最好将其jar显示声明,是项目结构清晰。
Unused declared dependencies found(没有用到却声明了),提示我们这些jar包没有用到,但我们声明了。这样的需要注意,我们不能简单地直接删掉其声明,而应该仔细分析。由于dependency:analyze只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它无法发现。
2.6.5.2.借用IDEA插件形式
Idea安装Maven-Helper
重启IDEA
打开pom文件
点击dependency analyze标签页
2.6.6.聚合
什么是聚合?
将多个项目同时运行就称为聚合。
如何实现聚合?
只需在pom中作如下配置即可实现聚合:
1.
2. web-connection-pool
3. web-java-crawler
4.
2.6.7.继承
什么是继承?
在聚合多个项目时,如果这些被聚合的项目中需要引入相同的Jar,那么可以将这些Jar写入父pom中,各个子项目继承该pom即可。
如何实现继承?
父pom配置:将需要继承的Jar包的坐标放入标签即可。
1.
2.
3.
4. cn.missbe.web.search
5. resource-search
6. pom
7. 1.0-SNAPSHOT
8.
9.
10.
子pom配置:
1.
2. 父pom所在项目的groupId
3. 父pom所在项目的artifactId
4. 父pom所在项目的版本号
5.
6.
7. resource-search
8. cn.missbe.web.search
9. 1.0-SNAPSHOT
10.
2.6.8.pom文件详解
pom文件的每个属性配置参考,传送门:https://www.cnblogs.com/sharpest/p/7738444.html
第三章 仓库
这节将介绍仓库的由来、布局、分类、配置、内部工作机制、镜像等概念
3.1.仓库的由来
在Maven世界中,任何一个依赖、插件或者项目构建的输出,都可以称为构件。得益于坐标机制,任何Maven项目使用任何一个构件的方式都是完全相同的。在此基础上,Maven可以在某个位置统一存储所有Maven项目共享的构件,这个统一的位置就是仓库。
实际的Maven项目将不再各自存储其依赖文件,它们只需要声明这些依赖的坐标,在需要的时候(例如,编译项目的时候需要将依赖加入到classpath中),Maven会自动根据坐标找到仓库中的构件,并使用它们。
为了实现重用,项目构建完毕后可生成的构件也可以安装或者部署到仓库中,供其他项目使用。
3.2.仓库的布局
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式。 该路经与坐标对应关系为groupId/artifactId/version/artifactId-version.packaging。 举个例子,比如下面这个分页插件依赖如下:
那他对应的仓库的路径就是这样:
1.
2. com.github.pagehelper
3. pagehelper-spring-boot-starter
4. 1.1.0
5.
Maven仓库是基于简单文件系统存储的,我们也理解其存储方式、因此,当遇到一些与仓库相关的问题时,可以很方便的查找相关文件,方便定位问题。
3.3.仓库的分类
3.3.1.本地仓库
一般来说,在Maven项目目录下,没有诸如lib/这样用来存放依赖文件的目录。当Maven在执行编译或测试时,如果需要使用依赖文件,它总是基于坐标使用本地仓库的依赖文件。
默认情况下,不管在Window还是Linux下,每个用户在自己用户目录下都有一个路径名为.m2/repository/的仓库目录。 如果你想自定义本地仓库目录地址。你可以编辑文件~/.m2/settings.xml,设置localRepository元素的值为想要的仓库地址,例如:
1.
2. D:\java\repository</localRepository>
3.
这样,该用户的本地仓库地址就被设置成了 D:\java\repository\。 需要注意的是,默认情况下,~/.m2/settings.xml文件不存在,用户需要从Maven安装目录复制$M2_HOME/conf/settings.xml文件再进行编辑。
3.3.2.远程仓库-中央仓库
由于最原始的本地仓库是空的,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令的时候下载到需要的构件。中央仓库就是这样一个默认的远程仓库,Maven的安装文件自带了中央仓库的配置。
中央仓库包含了这个世界上绝大多数流行的开源Java构件,以及源码、作者信息、SCM,信息、许可证信息等,每个月这里都会接受全世界Java程序员大概1亿次的访问,它对全世界Java开发者的贡献由此可见一斑。
3.3.3.远程仓库-私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。因此,一些无法从外部仓库下载到的构件也能从本地上传到私服上供大家使用。 私服的好处:
节省自己的外网速度
加速Maven构建
部署第三方构建
提高稳定性,增强控制
降低中央仓库的负荷
3.4.远程仓库的配置
在平时的开发中,我们往往不会使用默认的中央仓库,默认的中央仓库访问的速度比较慢,访问的人或许很多,有时候也无法满足我们项目的需求,可能项目需要的某些构件中央仓库中是没有的,而在其他远程仓库中有,如JBoss Maven仓库。这时,可以在pom.xml中配置该仓库,代码如下:
1.
2.
3. jboss
4. JBoss Repository
5. http://repository.jboss.com/maven2/
6.
7. true
8. daily
9.
10.
11. false
12. warn
13.
14. default
15.
16.
repository:在repositories元素下,可以使用repository子元素声明一个或者多个远程仓库。
id:仓库声明的唯一id,尤其需要注意的是,Maven自带的中央仓库使用的id为central,如果其他仓库声明也使用该id,就会覆盖中央仓库的配置。
name:仓库的名称,让我们直观方便的知道仓库是哪个,暂时没发现其他太大的含义。
url:指向了仓库的地址,一般来说,该地址都基于http协议,Maven用户都可以在浏览器中打开仓库地址浏览构件。
releases和snapshots:用来控制Maven对于发布版构件和快照版构件的下载权限。需要注意的是enabled子元素,该例中releases的enabled值为true,表示开启JBoss仓库的发布版本下载支持,而snapshots的enabled值为false,表示关闭JBoss仓库的快照版本的下载支持。根据该配置,Maven只会从JBoss仓库下载发布版的构件,而不会下载快照版的构件。
layout:元素值default表示仓库的布局是Maven2及Maven3的默认布局,而不是Maven1的布局。基本不会用到Maven1的布局。
其他:对于releases和snapshots来说,除了enabled,它们还包含另外两个子元素updatePolicy和checksumPolicy。
1:元素updatePolicy用来配置Maven从远处仓库检查更新的频率,默认值是daily,表示Maven每天检查一次。其他可用的值包括:never-从不检查更新;always-每次构建都检查更新;interval:X-每隔X分钟检查一次更新(X为任意整数)。
2:元素checksumPolicy用来配置Maven检查校验和文件的策略。当构建被部署到Maven仓库中时,会同时部署对应的检验和文件。在下载构件的时候,Maven会验证校验和文件,如果校验和验证失败,当checksumPolicy的值为默认的warn时,Maven会在执行构建时输出警告信息,其他可用的值包括:fail-Maven遇到校验和错误就让构建失败;ignore-使Maven完全忽略校验和错误。
3.5.远程仓库的认证
大部分的远程仓库不需要认证,但是如果是自己内部使用,为了安全起见,还是要配置认证信息的。 配置认证信息和配置远程仓库不同,远程仓库可以直接在pom.xml中配置,但是认证信息必须配置在settings.xml文件中。这是因为pom往往是被提交到代码仓库中供所有成员访问的,而settings.xml一般只存在于本机。因此,在settings.xml中配置认证信息更为安全。
1.
2. …
3.
4.
5.
6. releases
7. admin
8. admin123
9.
10.
11. …
12.
这里除了配置账号密码之外,值关键的就是id了,这个id要跟你在pom.xml里面配置的远程仓库repository的id一致,正是这个id将认证信息与仓库配置联系在了一起。
3.6.部署构件至远程仓库
我们自己搭建远程仓库的目的就是为了可以方便部署我们自己项目的构件以及一些无法从外部仓库直接获取的构件。这样才能在开发时,供其他对团队成员使用。 Maven除了能对项目进行编译、测试、打包之外,还能将项目生成的构件部署到远程仓库中。首先,需要编辑项目的pom.xml文件。配置distributionManagement元素,代码如下:
1.
2.
3. releases
4. public
5. http://59.50.95.66:8081/nexus/content/repositories/releases
6.
7.
8. snapshots
9. Snapshots
10. http://59.50.95.66:8081/nexus/content/repositories/snapshots
11.
12.
看代码,从命名上就看的出来区别,repository表示表示发布版本(稳定版本)构件的仓库,snapshotRepository表示快照版本(开发测试版本)的仓库。这两个元素都需要配置id、name和url,id为远程仓库的唯一标识,name是为了方便人阅读,关键的url表示该仓库的地址。
配置好了就运行命令mvn clean deploy,Maven就会将项目构建输出的构件部署到配置对应的远程仓库,如果项目当前的版本是快照版本,则部署到快照版本的仓库地址,否则就部署到发布版本的仓库地址。 当前项目是快照还是发布版本是通过 true 这个来区分的。忘记的同学在看看上面的## 远程仓库的配置。
3.7.镜像
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。用过Maven的都知道,国外的中央仓库用起来太慢了,所以选择一个国内的镜像就很有必要,我推荐国内的阿里云镜像。 阿里云镜像:配置很简单,修改conf文件夹下的settings.xml文件,添加如下镜像配置:
1.
2.
3. alimaven
4. aliyun maven
5. http://maven.aliyun.com/nexus/content/groups/public/
6. central
7.
8.
上例子中,的值为central,表示该配置为中央库的镜像,任何对于中央仓库的请求都会转至该镜像,用户也可以用同样的方法配置其他仓库的镜像
这里介绍下配置的各种选项
:匹配所有远程仓库。
external::匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。也就是说,匹配所有不在本机上的远程仓库。
repo1,repo2:匹配仓库repo1h和repo2,使用逗号分隔多个远程仓库。
*,!repo1:匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。
需要注意的是,由于镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven仍将无法访问被镜像仓库,因而将无法下载构件。
3.8.仓库服务搜索
这里介绍2个提供仓库服务搜索的地址:
Sonatype Nexus:https://repository.sonatype.org/
MVNrepository:http://mvnrepository.com/