目录java
Maven
,Ant
,Gradle
都是项目管理构建工具;apache
的一个颇为成功的开源项目,maven
主要服务于Java
平台的项目构建、依赖管理、项目信息管理// 查看版本 mvn -v // 清除target(项目生成的字节码文件) mvn clean // 编译项目 .java 文件转换为.class文件 mvn compile // 测试,测试以前已经进行了 mvn compile // 测试的类必须以Test结尾 mvn test // 打包项目 mvn package // 安装jar包到项目中 mvn install
<dependency> <groupId>com.zhao.MQTT</groupId> // 包名通常是公司的网址 + 项目名称 <artifactId>MQTT-Login</artifactId>// 通常是项目名称 + 模块功能名称 <version>1.0-SNAPSHOT</version> // 版本 <type>.....</type> // 依赖的类型,对应于项目坐标定义的packageing,大部分状况下不用申明,默认是jar <scope>....</scope>// 依赖的范围 <optional>...</optional> // 标记依赖是否可选 <exclusions> // 排除传递性依赖 <exclusion> ...... </exclusion> </exclusions> </dependency>
依赖范围就是用来控制依赖与三种classpath(编译classpath、测试classpath、运行classpath)的关系,maven有如下几种依赖范围:mysql
编译依赖范围。 若是没有指定,就会默认使用该依赖范围。使用此依赖范围的maven依赖,对于编译,测试,运行三种classpath都有效。典型的例子就是spring-core,在编译、测试和运行的时候都须要使用该依赖
测试依赖范围。 使用次依赖范围的maven依赖,只对于测试classpath有效,在编译主代码或者运行项目的使用时将没法使用此类依赖。典型的例子就是JUnit,它只有在编译测试代码及运行测试的时候裁须要
已提供依赖范围。 使用次依赖范围的maven依赖,只对于编译和测试classpath有效,可是运行时无效。
运行时依赖范围。 对于测试和运行classpath有效,可是在编译主代码时无效。典型的例子就是JDBC驱动的实现,项目主代码的编译只须要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候裁须要实现上述接口的具体JDBC驱动。
A依赖于B,B依赖于C,那么C就是A的一个传递性依赖;spring
依赖范围不只能够用来控制依赖和三种classpath的关系,并且还对传递性依赖产生影响。sql
假设A依赖于B,B依赖于C,那么咱们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围数据库
maven引入的传递性依赖机制,一方面大大简化和方便了依赖申明,另外一方面,大部分状况下咱们只须要关心项目的直接依赖是什么,而不是考虑这些直接依赖会引入什么传递性依赖。可是有时候,当传递性依赖形成问题的时候,咱们就须要清除的知道该传递性依赖是从那条依赖路径引入的。apache
项目A有这样的例子:A->B->C->X(1.0),A->D->X(2.0),X是A的传递性依赖,可是两个依赖路径上有两个版本的X,那么那个X会被maven解析使用呢?
两个版本的依赖都被解析显然是不对的,由于那样的话会形成依赖重复,所以必须选择一个。api
mavne的依赖调解机制的第一原则不能解决全部的问题,好比这样的依赖关系:
A->B->Y(1.0),A->C->Y(2.0),依赖路径都是2,那么到底谁会被解析使用呢?在maven以前的版本中,这是不肯定的,可是在maven2.0.9版本后,为了尽量的避免构建的不肯定性,maven定义了依赖的调解的第二原则:第一申明者优先,在依赖长度相等的状况下,在pom
表中依赖生命的顺序决定了谁会被解析使用。顺序最靠前的那个依赖优胜。例子中:若是B的依赖申明在C以前,那么Y(1.0)就会被解析使用。缓存
项目A依赖于项目B,项目B依赖于项目X和Y,B对于X和Y的依赖都是可选依赖:A->B、B->X(可选),B->Y(可选)。根据依赖性传递的定义,若是这个三个依赖的范围都是compile,那么X和Y就是A的compile范围传递性依赖。安全
可是这里的X、Y是可选依赖了,依赖将不会得以传递。换句话说:X,Y将不会对A有任何影响。springboot
好比B是一个持久层隔离工具包,它支持多种数据库,包括mysql,oracle,在构建的时候须要这两种数据库的驱动,可是在使用这个工具包的时候,只须要某一个驱动;
实际的应用中,咱们应该尽量的避免可选依赖的出现
传递性依赖会给项目隐式地引入不少依赖,这极大地假话了项目依赖的管理,可是有些时候这种特性也会带来问题,例如当前鲜蘑菇中有一个第三方依赖,而这个依赖因为某些缘由依赖了另一个类库的snapashot,那么这个snapshot就会成为当前项目的传递性依赖,而snpshot的不稳定性会直接影响到当前的项目。
有些时候你也可能想替换掉某个传递性依赖,换成本身想要的依赖。好比 sun jta api,hiberanate依赖与这个jar,可是因为版权的因素,该类库不在中央仓库中,而apache geronimo项目有一个对应的实现,这时候咱们就能够排除sun jat api,申明Geronimo的jta api实现。
不少关于spring framework的依赖,它们分别是org.springframework:spring-core:2.5.六、org.springframework:spring-context-support:2.5.6,它们都是来自同一个项目的不一样模块。所以浙西恶意来的版本都是相同的,并且是能够预见的,若是未来升级spring framework,这些依赖的版本会一块儿升级。
以下
<properties> <spring.version>4.3.9.RELEASE</spring.version> </properties> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency>
对于mavne来讲:仓库只分为两类:本地仓库和远程仓库。当maven根据左边寻找构建的时候,首先回去本地仓库,若是没有回去中央仓库,下载到本地,而后使用。
如何修改本地仓库地址?
<localRepository>/path/to/local/repo</localRepository>// 修改本地仓库的地址
每一个用户只有一个本地仓库,可是能够访问配置多个远程仓库
私服是一种特殊的远程仓库,是架设在局域网内部的仓库,私服代理广域网上的远程仓库,工局域网内的maven用户使用。当maven须要下载构建的时候,它从私服请求,若是私服上不存在该构建,则从外部的远程仓库下载。缓存在私服上以后,在为maven的下载请求提供服务。
一些没法从外部仓库下载到的构建也能从本地上传到私服上供咱们使用
不少状况下,默认的中央仓库没法知足项目的需求,可能项目须要的构建存在于另外一个远程仓库中,如JBoss Maven仓库中,这时,能够在pom表中配置该仓库,请注意实在pom表中
<repositories> <repository> <id>juziwl</id> <name>Juzi Repository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public </url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories>
大部分的远程仓库无需认证就能够访问,可是有时候处于安全方面的考虑,咱们须要提供认证信息才能访问一些远程仓库。
例如:组织内部有一个maven仓库服务器,该服务器为每一个项目都提供独立的maven仓库,为了防止非法的仓库访问,管理员为每一个仓库提供了一组用户名及密码。这时候为了能让maven访问仓库内容,就须要配置认证信息。
配置认证信息和配置仓库信息不一样,仓库信息能够直接配置在pom文件中,可是认证信息必须配置在settings.xml文件中。由于pom每每是被提交到代码仓库中共全部成员访问的,而settings.xml通常只放在本机。所以在settings.xml中配置认证信息更为安全。
<servers> <server> <id>juziwl3</id> <username>admin</username> <password>admin123</password> </server> </servers>
这里面的id很关键,必须和pom表中须要认证的repository元素的id彻底一致。换句话说,正是这个id降认证信息与仓库配置联系在了一块儿。
私服的最大用处就是部署第三方构建,包括组织内部生成的构建以及一些没法从外部仓库直接获取的构建,不管是平常开发中生成的构建,仍是正式版本发布的构建,都须要部署到仓库中供其余团队成员使用。
maven除了能对项目进行编译、测试、打包以外,还能够将项目生成的构建部署到仓库中。须要在pom.xml中进行配置。
<distributionManagement> <repository> <id>juziwl</id> <name>Juzi Repository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public</url> </repository> <distributionManagement> <snapshotRepository> <id>juziwl</id> <name>Juzi SnapshotRepository</name> <url>http://192.168.129.198:8081/nexus/content/groups/public</url> </snapshotRepository> </distributionManagement> </distributionManagement>
distributionManagement包含repository和snapshotRepository子元素,前者表示发布版本构件的仓库,后者表示快照版本的仓库。
往远程仓库部署构建的时候认证的。配置须要在settings.xml进行配置
<servers> <server> <id>juziwl3</id> <username>admin</username> <password>admin123</password> </server> </servers>
而后命令行:
mvn clean deploy
若是项目的当前的版本是快照版本,则部署到快照版本仓库地址,不然就部署到发布版本仓库地址。
若是仓库X能够提供仓库Y存储的全部内容,那么就能够认为X是Y的一个镜像,换句话说,任何一个能够从仓库Y获取的构建均可以从X获取。
settings.xml配置文件
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>
例子中:
关于镜像的一个更为常见的用法就是结合私服。因为私服能够代理任何外部的公共仓库(包括中央仓库),所以,对于组织内部的maven用户来讲,使用给一个私服地址就等于使用了全部须要的外部仓库,这能够将配置集中到私服,从而简化maven自己的配置,在这种状况下,任何须要的构建均可以从私服获取,私服就是全部仓库的镜像。
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors>
该例子中:
在maven中存在三套生命周期,每一套生命周期都是相互独立的,互不影响
cleanLifeCycle:清理的生命周期 clean defaultLifeCycle:默认的生命周期 compile,test,package,install,deploy siteLifeCycle:站点生命周期 site
之因此说是三套生命周期,是由于他们之间互不影响;
可是在一套生命周期以内执行后面的命令前面操做会自动执行;
从命令执行mavne任务的最主要方式就是调用maven的生命周期阶段。须要注意的是,各个生命周期是相互独立的,而一个生命周期的阶段四有先后依赖关系的。
maven的核心仅仅定义了抽象的生命周期,具体的任务是交由插件完成的,插件以独立的构建形式存在。
maven的生命周期与插件相互绑定,用以完成实际的构建任务。具体而言,是生命周期的阶段与插件的目标相互绑定,以完成某个具体的构建任务。例如项目编译这一任务,它对应了default生命周期的compile这一阶段,而maven-compile-plugin这一插件的compile目标可以完成该任务。所以将他们绑定,就能实现项目编译的目的。
完成了插件和生命周期的绑定以后,用户还能够配置插件目标的参数,进一步调整插件目标所执行的任务,以知足项目的需求。几乎全部的maven插件的目标都有一些可配置的参数,用户能够经过命令行和pom配置等方式来配置这些参数。
不少插件目标的参数都支持从命令行配置,用户能够在manve命令中使用-D参数,病伴随一个参数=参数值形式,来配置插件目标的参数。
例如:maven-surefire-plugin提供一个maven.test.skip的参数,当其值为true的时候,就会跳过执行测试。因而,在运行命令的时候,加上以下:
mvn install -Dmaven.test.skip=true
-D是java自带的,其功能就是经过命令行设置一个java系统属性,maven简单的重用了改参数,在准备插件的时候检查系统属性,便实现了插件参数的配置。
并非全部的插件参数都适合从命令行配置,有些参数的值从项目建立的发哦项目发布都不会改变,或者说不多改变,对于这种状况,在POM文件中一次性配置就显然比重复在命令行输入要方便。
用户能够在申明插件的时候,对此插件进行一个全局的配置。也就是说,全部该基于该插件目标的任务,都会使用这些配置。例如,咱们一般会须要配置maven-compiler-plugin 告诉它编译Java1.5版本的源文件,生成与JVM1.5兼容的字节码文件。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Maven聚合(或者称为多模块),是为了可以使用一条命令就构建多个模块,例如已经有两个模块,分别为account-email,account-persist,咱们须要建立一个额外的模块(假设名字为account-aggregator,而后经过该模块,来构建整个项目的全部模块,accout-aggregator自己做为一个Maven项目,它必须有本身的POM,不过做为一个聚合项目,其POM又有特殊的地方,看下面的配置
<?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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>demo</groupId> <artifactId>demo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>demo-springboot</module> <module>demo-java</module> <module>demo-provider</module> <module>demo-consumer</module> <module>demo-generator</module> </modules> </project>
上面有一个特殊的地方就是