一、是什么
maven是Apache下的一个纯Java开发的开源项目,它是一款能够抽象构建过程,并且提供依赖管理,中央仓库,项目构建等功能的工具。
二、为什么用
假如我们在开发两个Java项目,这两个项目中对于某一些功能会有互相依赖的情况,若两边共用一套代码进行关联,后期的维护会很繁琐,如果我们将共用的代码打成jar包引入项目中使用的话,那么后期进行代码更新的话也要对引入的jar进行更新也很麻烦。而maven可以完美解决这个问题。
1、普通的传统项目,包含jar包,占用空间很大。而Maven项目不包含jar包,所以占用空间很小。 maven不是不用jar包,而是将jar包转存在本地仓库中。
2、依赖管理,只需要在pom.xml配置需要的插件,就能在在项目中使用。主要是能够对jar包的统一管理,可以节省空间。
3、项目一键构建,maven可以进行编译、测试(junit)、运行、打包、部署。一个 tomcat:run命令就能把项目运行起来。
三、maven仓库
Maven有三种仓库:本地仓库,自己维护;远程仓库(私服),公司维护;中央仓库,maven官方维护。
如果想要修改maven的本地仓库位置,可以在maven的安装目录下的conf目录下的settings.xml配置文件中设置。找到localRepository标签,在里面写入想定义的地址全路径即可。
<localRepository>F:\maven\repository<localRepository>
在寻找jar包时,本地项目会先到本地仓库查找,如果有,直接使用,如果没有,会到远程仓库找,找到会下载到本地,没找到,会到中央仓库找,找到后本地仓库和远程仓库都会缓存一份。以便以后使用。当然如果没有远程仓库,则直接到中央仓库查找。
中央仓库地址:http://repo1.maven.org/maven2/;
关于远程仓库配置在文末介绍。
四、依赖管理
4.1、依赖配置
pom.xml文件中进行jar包管理时就如下一样。依赖配置主要包含以下元素:
groupId、artifactId和version:依赖的基本坐标
type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值为jar。
scope:依赖的范围
optional:标记依赖是否可选
exclusions:用来排除传递性依赖
<!--添加依赖配置-->
<dependencies>
<!--项目要使用到junit的jar包,所以在这里添加junit的jar包的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!--项目要使用到Hello的jar包,所以在这里添加Hello的jar包的依赖-->
<dependency>
<groupId>me.gacl.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
我们可以到https://search.maven.org/ 或者 https://mvnrepository.com/上查找依赖坐标信息。
4.2、依赖范围
scope范围 | 备注 |
---|---|
compile | 默认情况下就是compile类型, 意味着该依赖既要参与编译又要参与后期的测试等环节 |
test | 表示该依赖仅仅参加和测试有关的工作 |
provided | 可以参与编译,测试,运行等周期, 但是在打包的时候会进行exclude的相应操作, 其他方面和compile差异不大 |
runntime | 在编译环节不会参与进来,个人感觉和compile差异不大 |
system | 通常是指不从仓库读取依赖,而是通过本地路径来读取依赖, 因此常与systemPath标签结合使用 |
import | Maven2.0.9之后新增的范围,只能用在<dependencyManagement>中,并且导入的type为pom类型的父工程配置,一般用来解决多继承问题。 |
4.3、依赖原则
4.3.1、最短路径原则:
A -> B -> C -> D(d1)
F -> G -> D(d2)
这个时候项目中出现了两个版本的D,这时maven会选择d2版本的D,因为d1版本的D依赖路径长度为3,而d2版本的D整个依赖路径长度为2。
4.3.2、优先声明原则:
A -> B -> D(d1)
F -> G -> D(d2)
如果两个jar包版本路径深度相同,则使用优先声明的版本,也就是说会选择d1版本的jar包文件引入。
4.3.3、直引选择最后原则:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.17.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
如果在pom文件中,同时直接引用了如上两个版本,则会使用最后一次引用的jar包,也就是4.3.20.RELEASE版本。
五、maven生命周期
maven具有三套独立的生命周期:clean、default、site
在maven中,只要在同一个生命周期,你执行后面的阶段,那么前面的阶段也会被执行,而且不需要额外去输入前面的阶段。例如执行pre-clean,只会执行pre-clean,执行post-clean的话,会依次执行pre-clean、clean、post-clean。
clean:构建之前的清理工作、移除上一次构建生成的文件
pre-clean和post-clean分别是准备工作和收尾工作。
default:构建的核心部分,编译、测试、打包、安装、部署等等
compile:编译源代码;
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署;
package 接受编译好的代码,打包成可发布的格式,如 JAR 。
install 将包安装至本地仓库。
deploy 将最终的包复制到远程的仓库。
site:生成项目报告,站点,发布站点
pre-site :执行一些需要在生成站点文档之前完成的工作;
site:生成项目的站点文档;
post-site:后续工作,并为部署做准备;
site-deploy:将生成的站点文档部署到指定服务器
实际上,我们最常用的就是下面这几个:clean:有问题,多清理;package:打成Jar or War包,会自动进行clean+compile;install:将本地工程Jar上传到本地仓库;deploy:上传到私服
六、其他
1. 关于jar包、war包和install指令
jar包:扩展名是.jar,是java application archive的简称,包含java的普通类库、资源、辅助文件等。例如在使用maven之前,需要什么架包都是手动导入的,比如需要连接mysql数据库的架包,就把这个架包通过pom.xml引入,或者手动拷贝到lib文件夹下,这些架包都是jar包。
war包:扩展名为.war,是Web application archive的简称,是web应用程序,一个Web应用程序包括单独的一组文件、类和资源,有class文件,也有jsp文件等。例如开发项目过程中,项目需要部署在Tomcat下才能运行,启动Tomcat前,先把项目发布到Tomcat指定目录下,启动Tomcat后,Tomcat就会把整个项目进行编译运行。当你想部署一个web项目时,就把它打成war包去运行吧。
maven的install指令会将项目打包,打包类型例如SSM框架,会在pom.xml中体现,如果是war包结构,则会打包成war包,如果是jar包结构,则会打包成jar包。
新打的包位置在项目根目录下target文件夹下。
2. 关于远程仓库的配置
如果要配置远程仓库的话,一般有两种方式进行配置。项目在本地仓库找不到jar包会去远程仓库寻找。
首先了解一下maven配置文件加载优先级:pom.xml -> /用户目录/.m2/settings.xml -> /maven安装目录/conf/settings.xml
2.1 在pom.xml文件中配置:此方式配置为局部配置,有效范围仅为当前项目
<repositories>
<repository>
<id>nexus-mvn</id>
<name>maven nexus</name>
<url>http://118.196.1.220:8000/repository/maven-public/</url>
</repository>
<repository>
<id>aliyun-mvn</id>
<name>maven aliyun</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
repositories标签中可配置一个或多个仓库repository。如果在一个远程仓库中不到,会自动去其他仓库找。id:自定义唯一标识,name:自定义仓库名称,url:远程仓库地址, releases 的enable设置为true,告诉maven可以下载releases(稳定版本)的构件;snapshots 的enable 为false,即为禁止下载snapshot(开发中、不稳定)的构件,选项只能为true或false。
2.2 在settings文件中配置:此方式为全局配置,对应该maven的所有项目有效。
大部分远程仓库无需认证,但是也有一些需要认证信息才可以访问,一般企业级应用中访问指定远程仓库可能会用到认证信息,这样安全性更高。认证信息必须设置在settings文件中,如下:
<settings>
...
<!--配置远程仓库认证信息-->
<servers>
<server>
<id>roroBear</id>
<username>roroBear</username>
<password>ILoveMaven</password>
</server>
</servers>
...
</settings>
id:唯一标识,username:用户名;password:密码。认证信息正确的话才可以访问到私服远程仓库。
settings文件中在profiles标签内可以配置远程仓库,将所有的repositories标签都放在profiles标签内,然后通过activeProfile标签指定id激活,这样就配置好了。不用在单独的项目中一个一个繁琐的配置了。
<settings>
...
<profiles>
<profile>
<id>roroBearRepo</id>
<!-- repositories and pluginRepositories ... -->
</profile>
</profiles>
<activeProfiles>
<activeProfile>roroBearRepo</activeProfile>
</activeProfiles>
...
</settings>
关于镜像:
镜像就像是仓库的分身一样,maven用户通过镜像可以获得镜像对应仓库的所有内容,镜像因为可以提供比例如中央仓库或私服仓库更快更迅速的服务,所以使用较多。镜像通过ID来路由到指定远程仓库,原本从远程仓库拿的jar包全部从镜像去拿,加速下载。
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
mirrorOf标签匹配的都是repository的id,例如上面<mirrorOf>central</mirrorOf>,所有从central(默认远程仓库)去拉取依赖的都将重定向从aliyun镜像中去拉取依赖,除了central外,mirrorOf内还可以是*、repo1,repo2、*,!repo1等形式。
<mirrorOf>*</mirrorOf> :匹配所有仓库请求,即将所有的仓库请求都转到该镜像上
<mirrorOf>repo1,repo2</mirrorOf> :将仓库repo1和repo2的请求转到该镜像上,使用逗号分隔多个远程仓库
<mirrorOf>*,!repo1</miiroOf> : 匹配所有仓库请求,repo1除外
以上!