maven实践--你所需要了解的maven
基本概念
是什么?
Maven是一个强大的Java项目构建工具。
什么是构建工具?
构建工具是将软件项目构建相关的过程自动化的工具。构建一个软件项目通常包含以下一个或多个过程:
- 生成源码(如果项目使用自动生成源码);
- 从源码生成项目文档;
- 编译源码;
- 运行单元测试
- 将编译后的代码打包成JAR文件或者ZIP文件;
- 将打包好的代码安装到服务器、仓库或者其它的地方;
- 叙述项目间的依赖关系
有些项目可能需要更多的过程才能完成构建,这些过程一般也可以整合到构建工具中,因此它们也可以实现自动化。
自动化构建过程的好处是将手动构建过程中犯错的风险降到最低。而且,自动构建工具通常要比手动执行同样的构建过程要快。
核心概念:POM文件(POM project object mode项目对象模型)
POM文件是以XML文件的形式表述项目的资源,如源码、测试代码、依赖(用到的外部Jar包)等。
pom主要组成部分:

简单运行
当你安装好了Maven,并且在项目的根目录下创建了POM文件,可以在项目上运行Maven了。
mvn clean install
该命令首先执行clean构建周期,删除Maven输出目录中已编译的类文件,然后执行install构建阶段。
maven深入实践
构建生命周期
Maven中内置了三个构建生命周期:default,clean和site。default生命周期处理工程的部署,clean生命周期处理工程的清理,而site生命周期则负责创建工程的站点文档。
packaging直接影响Maven的构建生命周期。
在Maven 3中,其可用的打包类型如下:
- jar,默认类型
- war
- ejb
- ear
- rar
- par
- pom
- maven-plugin
如果想一次打包多个项目,可采用聚合类型pom,它通常由一个父模块和若干个子模块构成。
<packaging>pom</packaging>
<modules>
<module>zy-service-consumer</module>
<module>zy-eureka-server</module>
<module>zy-zipkin-service</module>
<module>zy-hystrix-dashboard</module>
</modules>
构建生命周期是由阶段组成的
三个构建生命周期都是由一系列不同的构建阶段组成,每一个构建阶段代表了生命周期的一个阶段。
以default生命周期为例,它是由以下的阶段组成
- validate – 验证该项目是否正确,所有必要的信息都是可用的
- compile – 编译工程源码
- test – 使用一个合适的单元测试框架测试编译的源代码。这些测试的代码不会被打包或部署到项目中
- package – 将编译的代码打包成它发布的格式,例如JAR
- integration-test – 如果必要的话,该命令会将工程处理并部署在一个集成测试运行的环境中
- verify – 运行任何检查以验证该包是否有效,是否符合质量标准
- install – 将工程打包安装到本地仓库中,以便本地其他项目可以进行依赖
- deploy – 在集成或发布环境中,将最终工程打包复制到远程仓库中,用于与其他开发人员和项目共享
mvn deploy
它不仅执行指定的构建阶段,而且会执行指定构建阶段之前的每一个阶段。因此,执行
构建阶段使用的构建插件
mvn install
[INFO] ------------------------------------------------------------------------
[INFO] Building zy-zeromq 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ zy-zeromq ---
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ zy-zeromq ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ zy-zeromq ---
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ zy-zeromq ---
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ zy-zeromq ---
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ zy-zeromq ---
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ zy-zeromq ---
(查看完整的生命周期阶段列表,请参考生命周期参考)
仓库
仓库只分为两类:本地仓库和远程仓库。
当Maven根据坐标寻找构建的时候,首先会查看本地仓库,如果本地仓库存在此构件,则直接使用;如果本地仓库不存在此构件,或者需要查看是否有更新的构件版本,Maven就会到远程仓库查找,发现需要的构件后,将其下载到本地仓库再使用。如果本地仓库和远程仓库都不存在需要的构件,则报错。

私服
私服的好处:节约外网的带宽,加速Maven的构建,方便部署第三方构件,稳定等

部署到远程仓库
将本项目jar包上传到私服、远程仓库,供项目组或其他人使用。配置如下:
pom.xml
<distributionManagement>
<repository>
<id>thirdparty</id>
<name>3rd party</name>
<url>http://192.168.100.103:8081/nexus/content/repositories/thirdparty/</url>
</repository>
</distributionManagement>
settigns.xml配置认证
<servers>
<server>
<id>thirdparty</id>
<username>repo-user</username>
<password>repo-psw</password>
</server>
</servers>
mvn命令:
本地仓库 的更新
mvn clean package install
远程 仓库 的更新
mvn clean package deploy
如果编译出问题时,可以执行如下命令
mvn clean install -e -U
-e详细异常,-U强制更新
为了加速下载,可以配置一些镜像mirror。
依赖
依赖传递性
- 子项目可以继承父项目的依赖
- 项目A依赖项目B,项目A-->项目B,项目B中的依赖也会被加入到项目A中。
由于依赖的传递性,导致项目中存在多个同名的jar包,存在jar包冲突等。maven提供的以下机制来解决这些问题:
依赖调解原则
过从Maven 2.0.9开始,POM中依赖声明的顺序决定了哪个版本会被使用,也叫作”第一声明原则”。
依赖管理
在多模块应用中,可能多个子项目会有共同的依赖。
在顶层的pom中指定依赖项的版本,以便让所有的子项目使用同一版本。dependency management只是依赖的一个声明,子项目需显式引用,但不用指定版本号。
父项目pom
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
子项目pom,需显式引用依赖,但不用指定版本号。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
依赖范围
- compile 默认的scope,表示 dependency 都可以在生命周期中使用。而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布
- provided 跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性。
<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
- runtime 表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段。
- system 跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。
- import(Maven2.0.9及以上)
import范围只适用于pom文件中的部分。表明指定的POM必须使用部分的依赖。因为依赖已经被替换,所以使用import范围的依赖并不影响依赖传递。 - test 范围表明使用此依赖范围的依赖,只在编译测试代码和运行测试的时候需要,应用的正常运行不需要此类依赖。
依赖排除
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
- 小技巧:一般在编译时类找不到,但是实际存在jar冲突情况时。在idea中安装Maven Helper插件,根据jar名称搜索,定位到具体的依赖,在依赖中排除冲突jar包。
可选依赖
可选的依赖工作原理
Project-A -> Project-B
上面的图意味着项目A依赖于项目B,当A在它的POM文件中把B声明为一个可选的依赖,他们的关系依然没有改变。仅仅就像一次正常的构建,在这次构建中,项目B将会被添加进classpath。
Project-X -> Project-A
但是当一个其他的项目(项目X)在它的POM文件中声明项目A为一个依赖,这个可选的依赖就发挥作用了。你将会注意到项目X的classpath不会包含项目B:为了把B包含进项目X的classpath,你需要在你的POM文件中直接声明。
例子:
有一个名为X2的项目,这个项目和hibernate有一些类似的功能,支持许多数据库驱动/依赖,比如说MySQL,postgre,oracle等。为了构建X2,所有的这些依赖都是必须的,但是对于你的项目来说却不是必须的,所以对于X2把这些依赖声明为可选的是非常实用的,不论什么时候当你在POM文件中把X2声明为一个直接依赖的时候,所有被X2支持的驱动不会自动的被包含进你的项目的classpath,你需要直接声明你将要使用的数据库的依赖/驱动。
自定义打包maven-assembly-plugin
在运行mapreduce/storm时,一般是以jar包方式运行,每个jar包中依赖的jar的包,可以采用maven-assembly-plugin。
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}-${project.version}</finalName>
<attach>false</attach>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase><!-- 绑定到package生命周期阶段上 -->
<goals>
<goal>single</goal><!-- 只运行一次 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
assembly.xml
<!--是否生成和项目名相同的根目录-->
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/target/classes</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
<!--<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>./</outputDirectory>
</fileSet>-->
</fileSets>
<dependencySets>
<dependencySet>
<!--是否把本项目添加到依赖文件夹下-->
<useProjectArtifact>false</useProjectArtifact>
<outputDirectory>/lib</outputDirectory>
<!--<excludes>
<exclude>org.apache.storm:storm-core</exclude>
</excludes>-->
</dependencySet>
</dependencySets>
其他常见配置方法
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
...
</configuration>
这种方式打出的包是fat jar,也就是把依赖的jar包全部解压成class文件后,再与自己的代码打成一个jar包。
maven assembly
命令
- mvn clean 清除目标目录中的生成结果
- mvn package 依据项目生成 jar 文件,打包之前会进行编译,测试
- mvn install在本地 Repository 中安装 jar
跳过测试类 : -Dmaven.test.skip=true
下载jar包源码: -DdownloadSource=true
下载javadocs: -DdownloadJavadocs=true
Archrtype
原型(Archetype)是一个Maven工程模板工具包。
maven-archetype-quickstart用得比较多。
maven vs gradle
- maven和gradle的比较与使用
总的来说,gradle相比于maven有很打的灵活性,目前gradle的使用者越来越多。而由于maven之前处于主流,并且在某些方面maven较gradle还有一些优点,所以maven和gradle并存。在github上大多数优秀的开源项目会同时提供maven和gradle两种添加依赖的方式。
参考文献
tips:本文属于自己学习和实践过程的记录,很多图和文字都粘贴自网上文章,没有注明引用请包涵!如有任何问题请留言或邮件通知,我会及时回复。
maven实践--你所需要了解的maven的更多相关文章
- 学习笔记——Maven实战(四)基于Maven的持续集成实践
Martin的<持续集成> 相信很多读者和我一样,最早接触到持续集成的概念是来自Martin的著名文章<持续集成>,该文最早发布于2000年9月,之后在2006年进行了一次修订 ...
- Maven实战(四)——基于Maven的持续集成实践
Martin的<持续集成> 相信非常多读者和我一样.最早接触到持续集成的概念是来自Martin的著名文章<持续集成>.该文最早公布于2000年9月,之后在2006年进行了一次修 ...
- maven 实践 :管理依赖
有人认为Maven是一个依赖管理工具,当然这种想法是错误的(确切的说Maven是一个项目管理工具,贯穿了整个项目生命周期,编译,测试,打包,发布...),但Maven给人造成这种错误的印象也是有原因的 ...
- 学习笔记——Maven实战(七)常用Maven插件介绍(上)
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven-compiler-plugin完成的.进一步说,每个任务对应了 ...
- 学习笔记——Maven实战(八)常用Maven插件介绍(下)
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...
- Maven使用笔记(七)Maven使用问题记录
1.Java-maven异常-cannot be cast to javax.servlet.Filter 报错 tomcat 启动后先将tomcat/lib目录下的jar包全部读入内存,如果weba ...
- Maven学习总结(28)——Maven+Nexus+Myeclipse集成
Maven简介 Maven 是一个基于项目对象模型(POM)的,提倡约定优于配置(ConventionOver Configuration)的,跨平台的项目管理和构建自动化工具. 首先它是一个优秀的构 ...
- Maven学习总结(14)——Maven 多模块项目如何分工?
一.开场白 使用Maven有段时间了,只能感慨真是个好东西,让我从传统模式体会到了严谨.规范.敏捷.方便的特性. 如果你懂Maven或许看过Juven翻译的<Maven权威指南>: 发个牢 ...
- Maven项目构建利器02——安装Maven核心程序
1.Maven也是用Java编写的工具,同样运行在JVM上,所以我们在安装Maven之前需要确保已经安装了JDK,首先来检查电脑上是否安装JDK. 2.如上图说明电脑中已经安装了JDK,下面就要去官网 ...
随机推荐
- TP5模型belongsTo和hasOne这两个方法的区别
在使用tp5模型的ORM的时候出现belongsTo和hasOne都有表示一对一的关系,但是二者并不相同.以下举例说明两者的区别: 首先有user表 字段 id name password字段 然后有 ...
- 快速排序的js实现
该方法的基本思想是: 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边. 3.再对左右区间重复第二步,直到各区间只有一个数. var ...
- 【转帖】Ubuntu : apt-get 命令
Ubuntu : apt-get 命令 https://www.cnblogs.com/sparkdev/p/11339231.html ubuntu的 我一直不熟 感谢作者 总结的这么好 在学习一下 ...
- [转帖]图说Docker架构的各种信息
图说Docker架构的各种信息 2018-07-18 15:16:04作者:linux人稿源:运维之美 https://ywnz.com/linuxyffq/2344.html 介绍Docker架 ...
- length 和 size 区分
总是混淆length和size,今天专门区分一下 1.在java代码(.java)中 1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性: 2.length( ...
- spring-boot 使用 jackson 出错(五)
环境 jdk 6 tomcat 6.0.53 sts 4.4.2 maven 3.2.5 原因 spring boot 1.5.22.RELEASE 默认使用的 jackson 的版本是 2.8.x, ...
- 数位dp详解&&LG P2602 [ZJOI2010]数字计数
数位dp,适用于解决一类求x~y之间有多少个符合要求的数或者其他. 例题 题目描述 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除 ...
- Rsync快速入门实例(转)
三种主要数据传输方式 单主机本地目录间数据传输(类似cp) Local: rsync [OPTION...] SRC... [DEST] 借助rcp,ssh等通道来传输数据(类似scp) Access ...
- Hystrix服务容错保护
一.什么是灾难性雪崩效应? 造成灾难性雪崩效应的原因,可以简单归结为下述三种: 服务提供者不可用.如:硬件故障.程序BUG.缓存击穿.并发请求量过大等. 重试加大流量.如:用户重试.代码重试逻辑等. ...
- Java基础第二天--多态、接口
多态 多态的概述 同一个对象,在不同时刻表现出来的不同形态 多态的前提和体现 有继承/实现关系 有方法重写关系 有父类引用指向子类对象 public class Animal { public voi ...