Maven
-
为什么要用Maven?
- 在平时的开发当中,肯定会导入各种的第三方jar包,这些jar包之间会存在依赖关系.,而这些包之间还会存在版本兼容的问题,所以,对于包的管理就显得特别重要了
- 如果没有maven,你可能会经历如下的艰苦过程:
- 当jar包有依赖的时候,要去挨着下载对应的jar包
- 当jar包依赖有冲突的时候,要去挨个排查是哪里出的问题
- 当项目有新人加入的时候,要去拷贝大量的jar包,进行重复构建
-
什么是Maven?
-
Maven是一个java项目管理工具,主要功能是统一开发规范与包的管理
-
项目构建工具:
- 用来将源代码构建成可以发布的构建工具.
-
依赖管理工具
-
用来管理jar包之间的依赖,只需要在指定的pom.xml文件中写入这些jar包的依赖属性,就会自动进行下载管理这些jar包.
-
pom.xml: 项目对象模型
<-- 依赖导入:通过坐标来进行注入 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE</version> </dependency>
-
-
项目信息聚合工具:
- 管理项目的信息相关内容,开发者信息,版本号等
-
-
Maven的安装和配置
-
官网下载maven的安装包:
http://maven.apache.org/download.cgi
-
配置环境变量:(类似于jdk的配置)
- 新建系统环境变量MAVEN_HOME,变量值填写maven的安装路径,不到bin.
- 找到Path环境变量: 在变量值后面加%MAVEN_HOME%/bin;.
- 验证: cmd输入 maven -version,出现maven的版本信息,说明安装成功
-
配置maven的本地仓库:
-
如果不配置本地仓库,那么会自动将远程下载的jar包放在如下位置
C:\Users\Administrator.m2\repository;
-
打开maven的安装目录,找到conf下的settings.xml,打开.
-
找到配置文件中的
<localRepository>/path/to/local/repo</localRepository> <-- 这段配置信息在注释里面,将其复制放出来,在路径填写你的本地仓库路径 --> <localRepository>D:\userData\repo</localRepository>
-
-
配置maven的中央仓库:
-
当在构建maven项目的时候,会先检查pom.xml文件,确定依赖包的位置将其下载:
- 首先会在本地仓库中查找获取依赖包,如果没有,则往下执行
- 从中央仓库查找获取依赖包,如果没有,则往下执行
- 如果在pom.xml中定了自定义的远程仓库,那么也会在这里的仓库中查找获取依赖包,如果都没找到,maven会抛出异常
-
配置中央仓库:这里建议使用阿里云的中央仓库
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
-
-
-
使用命令行创建maven项目
- 输入命令:
mvn archetype:generate
,回车,然后会出现选择骨架的选项( 默认是7 ),可以在上面信息看到7:xxxxxx-quickstart
,这个表示你将要创建的是一个java项目,回车即可. - 如果你需要创建javaWeb项目,则输入10, 这个选项是
10:xxxx-webapp
,表示你将要创建的是一个javaWeb项目,回车即可. - 输入项目坐标:
- 第一个:
groupId
,这个表示你的组织号,例如你是哪一个公司的等com.li
- 第二个:
artifactId
,这个表示项目名,mavendemo
- 第三个:
version
,表示版本号 - 第四个:
package
,表示包结构 - 回车即可
- 第一个:
- 输入命令:
-
maven创建的项目的目录结构
-
javaSe项目目录:
- src(项目源码) ->
- main(业务代码) , test(测试代码) ->
- java(核心代码) ,resources(配置文件,例如spring的xml配置文件,properties文件)->
- 包路径 -> java类
- java(核心代码) ,resources(配置文件,例如spring的xml配置文件,properties文件)->
- main(业务代码) , test(测试代码) ->
- src(项目源码) ->
-
javaWeb项目目录:
- 与java项目相比,在main里面多了webapp目录
-
-
依赖范围:
-
<-- 通过scope来指定依赖范围 -> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency>
-
什么是依赖范围?
-
maven项目不同阶段引入到classpath中的依赖是不同的,例如,编译时,maven会将编译相关的依赖引入classpath中,测试时,maven会将测试相关的依赖引入到classpath中,运行时,则会将运行时相关的依赖引入classpath中,依赖范围就是用来控制依赖于这三种classpath的关系的
-
有哪些依赖范围?
-
compile : 编译依赖范围 :该范围就是默认的依赖范围(不写scope就是默认),此依赖对于编译,测试,运行三种classpath都有效,会随着项目一起打包发布,例如:springframwork
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>2.5</version> <scope>compile</scope> <!--默认为该依赖范围,无须显示指定--〉 </dependency>
-
test : 测试依赖范围 : 这个范围是针对测试的,只对测试classpath才有效,在编译主代码和运行项目的时候,都无法使用该依赖,不会随着项目发布,例如:junit
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency>
-
runtime : 运行时依赖范围 : 使用该范围的依赖只对测试和运行时的classpath有效,对编译时是无效的.例如JDBC驱动,适用运行和测试阶段.
不过runtime的地方改成compile也不会出大问题.
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> <scope>runtime</scope> </dependency>
-
provided :环境提供依赖范围 : 使用该范围的依赖,只对编译和测试的classpath有效,对运行的classpath无效,最直接的例子就是servlet-api,在项目编译和测试的时候需要用到该依赖,但是在运行时,web容器(tomcat)已经提供了该依赖,如果不显示指定这个依赖范围的话,那么可能会由于tomcat依赖的版本不一样而造成版本冲突的情况:
<dependency> <groupId>javax-servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency>
-
system : 系统依赖范围 :该范围与provided所表示的依赖范围一致,只是system必须通过systemPath元素显式的指定依赖文件的路径,并不是通过maven仓库解析的,往往与本机系统进行绑定,可能会造成构建的不可移植性( 系统的不同,Windows与Linux之类的 ),所以,需要谨慎的使用(一般不用)
-
-
-
-
依赖继承
- 在maven项目中,子项目可以继承父项目中的依赖;
- 比如我们有一个父项目( maven-father),该父项目有一个子项目( maven-child),父项目中引入了依赖junit,就算在子项目中我们没有引入junit依赖,但是我们依旧能够在子项目中使用junit,因为子项目天然继承了父项目中的junit依赖,在Idea中,我们可以查看子项目的依赖结构图,可以看到子项目中含有junit依赖
-
依赖传递
-
在maven项目中,依赖是可以传递的;
-
有三个项目A,B,C. A -> B ->C,项目A依赖项目B,项目B依赖项目C,那么可以得出项目A依赖项目C( A ->C )
-
下面贴上依赖关系的代码:
<-- 项目A: --> <dependencies> <dependency> <groupId>com.li</groupId> <artifactId>B</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
项目B: <dependencies> <dependency> <groupId>com.li</groupId> <artifactId>C</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
项目C: <dependencies> </dependencies>
-
进行测试:
在项目C中写入如下代码: public class DoIt(){ public String doI(){ return "C项目中的dotest"; } } 在C项目中测试类中写如下代码: public class TestDoIt(){ public void test(){ DoIt doIt=new DoIt(); doIt.doI(); } } 在C项目中运行测试代码,会在控制台输出 : 'C项目中的dotest'
-
我们将C项目中的测试代码复制到A项目和B项目里面进行运行,可以看见控制台也会打印出
C项目中的dotest
这样一句话,在A项目和B项目里面并没有DoIt这个类, 这就验证了依赖的传递
的这个性质了.
-
-
能进行依赖传递的前提:
- 只有依赖范围为compile和runtime的依赖是传递的
-
依赖传递的一些规则:
- 简单传递依赖:
- A -> B -> C => A-B A ->C
- 最短路径原则:
- 谁离得近就使用谁的依赖( jar包 )
- A到C的路径为 :A ->B ->C
- A到B的路径为: A ->B
- 如果C中使用的druid版本是 1.0
- B中使用的druid版本是 1.1
- 那么根据最短路径原则,A中依赖的druid版本就是1.1
- 第一声明优先原则:
- 当路径长度相同的时候,会使用到第一声明优先原则
- A -> B -> C(1.0)
- A -> D ->C(2.0)
- 此时A ->C(1.0)和C(2.0)的依赖路径是一样的,在pom中,谁写在前面就会决定使用谁的依赖
- 简单传递依赖:
-
排除依赖传递
-
使用
exclusions
声明不需要传递的依赖 -
A -> B ,项目A依赖与项目B,通过依赖的传递,项目B中的jar包会传递到A当中来.
-
如果项目A中与项目B中使用了相同的版本号不同的jar包,那么此时就会出现依赖冲突,就可以使用
exclusions
标签来将项目B中不想他传递的jar包包起来;<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> <-- 不想其依赖传递的一些jar包 --> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency>
-
-
版本管理器(dependencyManagement )
-
在maven中,
dependecyManagement
这个标签相当于对所依赖jar包的管理器,只做声明; -
pom中,jar的版本判断有两种方式:
- 如果在
dependencies
中有自己声明version
元素,那么不管dependencyManagement
里面有没有对该jar版本的声明都会以dependencies
里面的version
为准. - 如果在
dependencies
里面没有对导入的依赖声明version
,那么maven就会根据groupId
和artifactId
去dependencyManagement
里面找有没有对此jar包的声明,如果有就继承这个version
,没有机会报错.
- 如果在
-
dependencyManagement
只是声明依赖,并不会实现依赖的引入,因此子项目需要显示声明需要用的依赖. 如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本 .<-- 只是对版本进行管理,不会实际引入jar --> <dependencyManagement> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.0.RELEASE</version> </dependency> </dependencyManagement>
<-- 会实际下载jar包 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> </dependencies>
-
-
maven中的常用命令
- maven clean : 对项目进行清理,清理的过程中会删除targt目录下编译的内容
- maven compile : 编译项目源代码 , 编译后的内容会存放在target目录下
- maven test : 对项目的运行进行测试
- maven packet : 将项目打包,打包后的文件会存放到项目的target目录下,打包好的文件通常都是编译后生成的class文件
- maven install : 将自定义的maven项目,安装至本地仓库,可以供其他项目使用