什么是Maven
目前无论使用IDEA还是Eclipse等其他``IDE`,使用里面ANT工具。ANT工具帮助我们进行编译,打包运行等工作
Apache基于ANT进行了升级,研发出了全新的自动化构建工具Maven
Maven是Apache的一款开源的项目管理工具
以后无论是普通javase项目还是javaee项目,都使用Maven创建
Maven使用项目对象模型(POM)的概念,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。在Maven中每个项目都相当于是一个对象,对象(项目)和对象(项目)之间是有关系的。关系包含了:依赖、继承、聚合,实现Maven项目可以更加方便的实现导jar包、拆分项目等效果。
Maven仓库
Maven仓库是基于简单文件系统存储的,集中化管理Java API资源的一个服务
仓库中的任何一个构建都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径。得益于Maven的坐标机制,任何Maven项目使用任何一个构建的方式都是完全相同的。
Maven 可以在某个位置统一存储所有的 Maven 项目共享的构件,这个统一的位置就是仓库,项目构建完毕后生成的构件也可以安装或者部署到仓库中,供其它项目使用。
对于Maven来说,仓库分为两类:本地仓库和远程仓库。
远程仓库
不在本机中的一切仓库,都是远程仓库:分为中央仓库 和 本地私服仓库
远程仓库指通过各种协议如file://和http://访问的其它类型的仓库。这些仓库可能是第三方搭建的真实的远程仓库,用来提供他们的构件下载(例如repo.maven.apache.org和uk.maven.org是Maven的中央仓库)。其它“远程”仓库可能是你的公司拥有的建立在文件或HTTP服务器上的内部仓库,用来在开发团队间共享私有构件和管理发布的。
默认的远程仓库使用的Apache提供的中央仓库:https://mvnrepository.com/
本地仓库
本地仓库指本机的一份拷贝,用来缓存远程下载,包含你尚未发布的临时构件。
仓库配置
本地仓库是开发者本地电脑中的一个目录,用于缓存从远程仓库下载的构件。默认的本地仓库是${user.home}/.m2/repository。用户可使用settings.xml文件修改本地仓库。具体内容如下:
1 |
|
如果仓库A可以提供仓库B存储的所有内容,那么就可以认为A是B的一个镜像。例如:在国内直接连接中央仓库下载依赖,由于一些特殊原因下载速度非常慢。这时,我们可以使用阿里云提供的镜像http://maven.aliyun.com/nexus/content/groups/public/来替换中央仓库http://repol.maven.org/maven2/。修改maven的`setting.xml`文件,具体内容如下:
1 | <mirror> |
本地仓库优先级最高,镜像仓库次之,中央仓库优先级最低
JDK的配置
当你的idea中有多个jdk的时候,就需要指定你编译和运行的jdk,在settings.xml中配置:
1 | <profile> |
上述配置的前提是你的idea中要有1.8的jdk
Maven工程类型
- POM工程,POM工程是逻辑工程,用在父级工程或聚合工程中。用来做jar包的版本控制
- JAR工程,将会打包成jar,用作jar包使用。即常见的本地工程。Java Project
- WAR工程,将会打包成war,发布在服务器上的工程
Maven工程关系
Maven工具基于POM模式实现的。在Maven中每个项目都相当于是一个对象,对象(项目)和对象(项目)之间是有关系的,包括:依赖、继承、聚合实现Maven项目可以更加方便的实现导jar包、拆分项目等效果。
依赖
即A工程开发或运行过程中需要B工程提供支持,则代表A工程依赖B工程。在这种情况下,需要在A项目的pom.xml文件中增加配置定义依赖关系。
通俗理解就是导jar包,B工程可以是自己的项目打包后的jar包,也可以是中央仓库的jar包
如何注入依赖
在pom.xml文件的根元素project下的dependencies标签中,配置依赖关系。每个依赖deoendence标签都应该包含以下元素:groupId, artifactId, version

依赖省去了程序员手动添加jar包的操作,可以帮助我们解决jar包冲突问题
依赖的传递性
传递性依赖是Maven2.0的新特性。假设你的项目依赖于一个库,而这个库又依赖于其他库。你不必自己去找出所有这些依赖,你只需要加上你直接依赖的库,Maven会隐式的把这些库间接依赖的库也加入到你的项目中。这个特性是靠解析从远程仓库中获取的依赖库的项目文件实现的。一般的,这些项目的所有依赖都会加入到项目中,或者从父项目继承,或者通过传递性依赖。
如果A依赖了B,那么C依赖A时会自动把A和B都导入进来。创建项目后,选择IDEA最右侧Maven面板lifecycle,双击install后就会把项目安装到本地仓库中,其他项目就可以通过坐标引用此项目。
两个原则
第一原则:最短路径优先原则
意味着项目依赖关系树中路径最短的版本会被使用。假设A、B、C之间的依赖关系是A->B->C->D(2.0) 和A->E->(D1.0),那么D(1.0)会被使用,因为A通过E到D的路径更短
第二原则:最先声明原则
依赖路径长度是一样的的时候,第一原则不能解决所有问题,比如这样的依赖关系:A–>B–>Y(1.0),A–>C–>Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2。那么到底谁会被解析使用呢?在maven2.0.8及之前的版本中,这是不确定的,但是maven2.0.9开始,为了尽可能避免构建的不确定性,maven定义了依赖调解的第二原则:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。
排除依赖
exclusions: 用来排除传递性依赖 其中可配置多个exclusion标签,每个exclusion标签里面对应的有groupId, artifactId两项基本元素。注意:不用写版本号。
依赖范围
依赖范围就决定了你依赖的坐标 在什么情况下有效,什么情况下无效
compile
这是默认范围。如果没有指定,就会使用该依赖范围。表示该依赖在编译和运行时都生效
provided
已提供依赖范围。使用此依赖范围的Maven依赖。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍(如:servlet-api)
runtime
runtime范围表明编译时不需要生效,而只在运行时生效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动
system
系统范围与provided类似,不过你必须显式指定一个本地系统路径的JAR,此类依赖应该一直有效,Maven也不会去仓库中寻找它。但是,使用system范围依赖时必须通过systemPath元素显式地指定依赖文件的路径
test
test范围表明使用此依赖范围只在编译测试代码和运行测试的时候需要,应用的正常运行不需要此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候才需要。Junit的jar包就在测试阶段用就行了,你导出项目的时候没有必要把junit的东西到处去了就,所在在junit坐标下加入scope-test
import
import范围只适用于pom文件中的
注意:import只能用在dependencyManagement的scope里。
继承
如果A工程继承B工程,则代表A工程默认依赖B工程依赖的所有资源,且可以应用B工程中定义的所有资源信息,被继承的工程(B工程)只能是POM工程。
注意:在父项目中放在
放在
父工程是一个POM工程:

子工程:

本质上是POM文件的继承
聚合
当我们开发的工程拥有2个以上模块的时候,每个模块都是一个独立的功能集合。比如某大学系统中拥有搜索平台,学习平台,考试平台等。开发的时候每个平台都可以独立编译,测试,运行。这个时候我们就需要一个聚合工程。
在创建聚合工程的过程中,总的工程必须是一个POM工程(Maven Project)(聚合项目必须是一个pom类型的项目,jar项目war项目是没有办法做聚合工程的),各子模块可以是任意类型模块(Maven Module)。
聚合包含了继承的特性
聚合时多个项目的本质还是一个项目。这些项目被一个大的父项目包含。且这时父项目类型为pom类型。同时在父项目的pom.xml中出现


常见插件
编译器插件
通过编译器插件,我们可以配置使用的JDK或者说编译器的版本
在settings.xml文件中配置全局编译器插件,找到profiles节点,在里面加入profile节点
1 | <profile> |
配置编译器插件:pom.xml配置片段
1 | <!-- 配置maven的编译插件 --> |
资源拷贝插件
Maven在打包时默认只将src/main/resources里的配置文件拷贝到项目中并做打包处理,而非resource目录下的配置文件在打包时不会添加到项目中
我们的配置文件,一般都放在:src/main/resources,然后打包后配置文件就会在target的classes下面放着。
现在想把非resources下面的文件也打包到classes下面,需要配置pom.xml配置片段:
1 | <build> |
配置好以后,那么你设置的位置下的配置文件都会被打包了

tomcat插件
如果创建war项目,必然要部署在服务器上,方式有
- 部署在远程服务器上
- 将IDEA和外部tomcat产生关联,然后将项目部署在外部tomcat上
现在学习一个新的方式,不再依赖外部的tomcat,maven提供了tomcat插件,我们可以配置来使用
创建web项目:war项目

使用Tomcat插件发布部署并执行war工程的时候,需要使用启动命令,启动命令为:tomcat7:run。命令中的tomcat7是插件命名,由插件提供商决定。run为插件中的具体功能。
(注意:之前用的编译器插件,资源拷贝插件,不是可运行的插件,maven直接帮我们运行了,但是tomcat属于可运行插件,它什么时候工作需要程序员来控制,怎么控制呢?我们必须通过命令来运行控制)
具体pom.xml文件的配置如下:
1 | <build> |
Maven常见命令介绍
Maven的命令非常多,介绍常用的几个:(所有命令都可以在控制台运行的)
install
本地安装, 包含编译,打包,安装到本地仓库
编译 - javac
打包 - jar, 将java代码打包为jar文件
安装到本地仓库 - 将打包的jar文件,保存到本地仓库目录中。
clean
清除已编译信息。
删除工程中的target目录
compile
只编译————javac命令
package
打包。 包含编译,打包两个功能
package命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库
install命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库