Maven基础
1.Maven简介
1.1 Maven是什么
-
在学习Maven之前,我们先来看一下我们现在做的项目都有哪些问题。
-
假设你现在做了一个crm的系统,项目中肯定要用到一些jar包,比如说mybatis,log4j,JUnit等,
-
除了这些之外,你有可能用到你的同事开发的其他的东西,比如说别人做了一个财务模块或做了一个结算的模块,你在这里边有可能要用到这些东西。
-
那么带了的问题是:
-
假如有一天你们的项目中mybatis进行了一个升级,但是它内部使用的JUnit没有升级,你升级以后的mybatis假如要用5.0的JUnit,而你项目中目前用的是4.0的,会不会冲突?
-
必然会出问题!这个时候管理起来会比较麻烦,你需要各种调整。
-
更有甚者,假如同事做的这些东西升级了但又没有通知你,这个时候,就会出现几种严重的问题:
- (1)jar包不统一,jar不兼容
- (2)工程升级维护过程操作繁琐
-
除此之外,还会有其它的一系列问题。那么要解决这些问题,就用到了我们今天要讲的Maven了
那Maven是什么?
-
Maven的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)
-
Maven是用Java语言编写的
-
他管理的东西统统以面向对象的形式进行设计,最终他把一个项目看成一个对象
-
而这个对象叫做POM(project object model),即项目对象模型
-
我们说一个项目就是一个对象,作为对象的行为、对象的属性都有哪些呢?
-
Maven说我们需要编写一个pom.xml文件,Maven通过加载这个配置文件就可以知道我们项目的相关信息了!
-
到这里我们知道了Maven离不开一个叫pom.xml的文件。因为这个文件代表就一个项目。
- 提个问题大家思考,如果我们做8个项目,对应的是1个文件,还是8个文件?肯定是8个!
-
那Maven是如何帮我们进行项目资源管理的呢?这就需要用到Maven中的第二个东西:依赖管理。这也是它的第二个核心!
-
所谓依赖管理就是maven对项目所有依赖资源的一种管理,它和项目之间是一种双向关系,即当我们做项目的时候maven的依赖管理可以帮助你去管理你所需要的其他资源,当其他的项目需要依赖我们项目的时候,maven也会把我们的项目当作一种资源去进行管理,这就是一种双向关系。
-
那maven的依赖管理它管理的这些资源存在哪儿呢?主要有三个位置:本地仓库,私服,中央仓库
-
本地仓库顾名思义就是存储在本地的一种资源仓库,如果本地仓库中没有相关资源,可以去私服上获取,私服也是一个资源仓库,只不过不在本地,是一种远程仓库,如果私服上也没有相关资源,可以去中央仓库去获取,中央仓库也是一种远程仓库。
-
Maven除了帮我们管理项目资源之外还能帮助我们对项目进行构建,管理项目的整个生命周期,当然它的这些功能需要使用一些相关的插件来完成,当然整个生命周期过程中插件是需要配合使用的,单独一个无法完成完整的生命周期。
1.2 Maven的作用
Maven的作用我们可以分成三类:
(1)项目构建:提供标准的,跨平台的自动化构建项目的方式
(2)依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突等问题
(3)统一开发结构:提供标准的,统一的项目开发结构,如下图所示:
- 各目录存放资源类型说明:
- src/main/java:项目java源码
- src/main/resources:项目的相关配置文件(比如mybatis配置,xml映射配置,自定义配置文件等)
- src/main/webapp:web资源(比如html,css,js等)
- src/test/java:测试代码
- src/test/resources:测试相关配置文件
- src/pom.xml:项目pom文件
2.Maven环境搭建 ***
maven的官网:http://maven.apache.org/
2.1 下载
官方下载地址:http://maven.apache.org/download.cgi
2.2 安装
maven是一个绿色软件,解压即安装,非常容易,
我们找到今日课程资料中的安装程序
,将里面的apache-maven-3.6.1-bin.zip
直接解压到D盘根目录下即可
解压完成后我们可以查看一下maven自己的一个目录结构
各目录结构说明:
bin:可执行程序目录,
boot:maven自身的启动加载器
conf:maven配置文件的存放目录
lib:maven运行所需库的存放目录
2.3 环境配置
maven的运行需要java的环境,需要我们配置JAVA_HOME
环境变量,这个相信大家已经存在了
下面在去配置MAVEN_HOME
的环境变量
1:我的电脑
-------->属性
--------->高级系统设置
---------->新建系统变量MAVEN_HOME
,
系统变量值就是maven软件的根目录,我们刚刚已经将maven解压到D盘了,因此变量值就如图中所示
2 : 然后path中配置%MAVEN_HOME%\bin;目录
注意:最好给maven的环境变量放到java后边(java第一位,maven第二位)
3:环境变量配置好之后需要测试环境配置结果,我们需要在DOS命令窗口下输入以下命令查看输出
mvn -v
如果能够看到输出的maven的版本信息代表配置成功
3.Maven基础概念
3.1 仓库
仓库:用于存储资源,主要是各种jar包
关于仓库,我们前面讲到了有三种:本地仓库,私服,中央仓库,其中私服和中央仓库都属于远程仓库
中央仓库:maven团队自身维护的仓库,属于开源的
私服:各公司/部门等小范围内存储资源的仓库,私服也可以从中央仓库获取资源
本地仓库:开发者自己电脑上存储资源的仓库,也可从远程仓库获取资源
私服的作用:
(1)保存具有版权的资源,包含购买或自主研发的jar
(2)一定范围内共享资源,能做到仅对内不对外开放
3.2 坐标
我们说maven的仓库里存储了各种各样的资源(jar包),那这些资源我们如何找到它们呢?我们需要知道它们具体的一个位置才能知道如何找到它们,这个就叫坐标
坐标:maven中的坐标用于描述仓库中资源的位置
maven仓库地址:https://repo1.maven.org/maven2/
那maven中的坐标是如何构成的呢?
maven坐标的主要组成如下:
groupId:定义当前资源隶属组织名称(通常是域名反写,如:org.mybatis;com.ithe)
artifactId:定义当前资源的名称(通常是项目或模块名称,如:crm,sms)
artifact:制品,产品
version:定义当前资源的版本号
packaging:定义资源的打包方式,取值一般有如下三种
(1)jar:该资源打成jar包,默认是jar
(2)war:该资源打成war包
(3)pom:该资源是一个父资源(表明使用maven分模块管理),打包时只生成一个pom.xml不生成jar或其他包结构
maven坐标的作用:
使用唯一标识,唯一性定义资源位置,通过该标识可以将资源的识别与下载工作交由机器完成。
3.3 仓库配置
3.3.1 本地仓库
-
开发者要在自己电脑上做开发,首先要做的就是配置本地仓库
-
默认情况下maven本地仓库的位置在哪儿呢?
-
我们可以选择在全局进行配置,在maven的配置文件
conf/settings.xml
中可以找到它的说明<!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository> -->
-
也就是在系统盘当前用户目录下的
.m2/repository
,比如我当前的系统用户是zs
,则默认的本地仓库仓库位置在C:\Users\zs\.m2\repository
-
因为我们平时开发项目所有的资源会比较多,而且各种资源还有好多的版本,资源与资源之间还有相互依赖的这种情况,因此本地仓库保存的内容会非常的多,它的体积会很大,如果放在C盘下不太合适,因此我们可以自己来指定一个位置作为本地仓库的位置,这个指定同样是需要来修改maven的配置文件
conf/settings.xml
-
在我们前面查看这个文件的时候大家会发现它提供了一个标签
<localRepository>/path/to/local/repo</localRepository>
, -
这个标签中配置的值就是我们本地仓库的位置,但是这个标签是在注释中的,也就是说目前不起作用,因此我们要将该标签挪出注释,并修改标签内的值,指定一个新的位置作为本地仓库的位置,例如
<!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>/path/to/local/repo</localRepository> --> <localRepository>D:\maven\repository</localRepository> <!--D:\maven\repository这个目录需要自己创建出来-->
-
然后将这个修改好的settings.xml,复制到D:\maven目录下
-
这个settings.xml是子配置,而conf/settings.xml是主配置
-
-
注意:局部用户配置(子配置)优先与全局配置(主配置)(遇见相同配置项的时候)
3.3.2 远程仓库
-
另外大家需要注意:maven默认连接的远程仓库位置是:(即中央仓库)
-
此站点并不在国内,因此有时候下载速度非常慢,因此我们可以配置一个国内站点镜像,可用于加速下载资源
-
我们在
conf/settings.xml
配置文件中找到<mirrors>
标签,在这组标签下添加镜像的配置,如下
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
- 最后,还得将conf/settings.xml复制一份覆盖d:/maven/settings.xml
4.Maven项目搭建
4.2.2 使用原型创建项目
4.2.2.1 创建普通java工程
-
创建maven项目的时候选择使用原型骨架
- archetype:原型
- create from archetype:从原型创建,就是使用模板创建module
- maven-archetype-quickstart:就是创建ajva工程的模板(原型)
-
输入坐标信息
- 然后就一路下一步
-
创建完成后发现通过这种方式缺少一些目录
-
我们需要手动去补全目录,并且要对补全的目录进行标记,切记
4.2.2.2 创建web工程
- 选择web对应的原型骨架
有很多的webapp原型骨架,选择哪个基本都差不多,包括前面创建普通项目也是一样,quickstart原型也有很多
4.2.2.3 tomcat插件安装&web工程启动
pom.xml文件说明
<?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/maven-v4_0_0.xsd">
<!--指定pom的模型版本-->
<modelVersion>4.0.0</modelVersion>
<!--打包方式,web工程打包为war,java工程打包为jar-->
<packaging>war</packaging>
<!--组织id-->
<groupId>com.ithe</groupId>
<!--项目id-->
<artifactId>web01</artifactId>
<!--版本号:release,snapshot-->
<version>1.0-SNAPSHOT</version>
<!--设置当前工程的所有依赖-->
<dependencies>
<!--具体的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<!--构建-->
<build>
<!--设置插件-->
<plugins>
<!--具体的插件配置-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
5.Maven依赖管理
5.1 依赖配置与依赖传递
依赖是指在当前项目中运行所需的jar,依赖配置的格式
依赖传递:
依赖具有传递性,分两种
(1)直接依赖:在当前项目中通过依赖配置建立的依赖关系
(2)间接依赖:被依赖的资源如果依赖其他资源,则表明当前项目间接依赖其他资源
演示:
-
项目2依赖项目3
-
项目三添加junit
- 在项目2中发现也会有junit
- 这就是依赖传递
注意:直接依赖和间接依赖其实也是一个相对关系
依赖传递的冲突问题:
在依赖传递过程中产生了冲突,我们有三种优先法则
(1)路径优先:当依赖中出现相同资源时,层级越深,优先级越低,反之则越高
(2)声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖靠后的
(3)特殊优先:当同级配置了相同资源的不同版本时,后配置的覆盖先配置的
可选依赖:(不传递)
- 总结:可选依赖,是比如A引用B依赖,B自己内部提前设置了自己内部依赖是否传递
排除依赖:(不要传递的依赖)
- 总结:排除依赖,是A引用B依赖时,主动的排除B内部的依赖
5.2 依赖范围
依赖的jar默认情况可以在任何地方可用,可以通过scope
标签设定其作用范围
这里的范围主要是指以下三种范围
(1)主程序范围有效(src/main目录范围内)
(2)测试程序范围内有效(src/test目录范围内)
(3)是否参与打包(package指令范围内)
此外:scope
标签的取值有四种:compile,test,provided,runtime
-
compile:任何范围都可以使用
-
test:只能用于测试
-
provided:主代码与测试代码可用(理解:provided是提供支持,只给代码提供支持。线上运行不能用,只有在开发测试阶段能够用)
- servlet-api就是不用打包进去,因为代码打包完之后是运行在tomcat中,而tomcat中自带servlet-api这个包
-
runtime:打包可用(理解:runtime:运行时,这个运行是指定程序上线运行,与provided正好相反)
- jdbc这个jar包其实在代码中没有用过
- 因为我们并没有import导入jdbc中哪个类
- 只是用了他的类名,
Class.forName("com.mysql.jdbc.Driver")
依赖范围的传递性:
- 比如:项目1依赖项目2
- 那么项目1在依赖项目2时配置的范围,是横向的(直接依赖,因为项目1直接依赖了项目2)
- 那么项目2内部的依赖就属于间接依赖,是纵向的(间接依赖,因为项目1间接依赖了项目2的依赖)
6.Maven生命周期与插件
6.1 生命周期
maven的构建生命周期描述的是一次构建过程经历了多少个事件
当然maven的生命周期不止这一套,总共分为3套,每套里面包含的事件如下
(1)clean:清理工作 (初始阶段,比较干净,啥都没有,所以是清理)
pre-clean:执行一些在clean之前的工作
clean:移除上一次构建产生的所有文件
post-clean:执行一些在clean之后立刻完成的工作
(2)default:核心工作,例如编译,测试,打包,部署等 (使用阶段:工作中,做事情)
对于default生命周期,每个事件在执行之前都会将之前的所有事件依次执行一遍
(3)site:产生报告,发布站点等(结束阶段:工作完了之后,就需要生成报告,发布,相当于给出工作的结果)
pre-site:执行一些在生成站点文档之前的工作
site:生成项目的站点文档
post-site:执行一些在生成站点文档之后完成的工作,为部署做准备
site-deploy:将生成的站点文档部署到特定的服务器上
6.2 插件
前面我们讲了maven生命周期中的相关事件,那这些事件是谁来执行的呢?答案是maven的插件
插件:
- 插件与生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件
- maven默认在各个生命周期上都绑定了预先设定的插件来完成相应功能
- 插件还可以完成一些自定义功能
在maven官网中有对插件的介绍:
http://maven.apache.org/plugins/index.html
- jar代表将源码打包(main目录)
- test-jar代表将测试代码打包(test目录)
- phase [feɪz] 阶段 :代表哪个声明周期阶段开始打包
- generate-test-resources是在compile阶段
- 所以只写compile之后的操作都可以(这里执行的是install)