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,下面就要去官网 ...
随机推荐
- Redis(1.1)linux下安装redis
一.常见安装方式 [0]环境 OS:CentOS7.5 Redis:4.0.14 yum源:本地源 [1]检查安装 gcc 依赖环境 gcc -v#如果没安装会报错类似于 command not fi ...
- Separate String
Separate String 时间限制: 1 Sec 内存限制: 128 MB提交: 50 解决: 16 题目描述 You are given a string t and a set S of ...
- BZOJ 4835: 遗忘之树
传送门 首先设 $f[x]$ 表示点分树上 $x$ 的子树内的方案数 发现对于 $x$ 的每个儿子 $v$ ,$x$ 似乎可以向 $v$ 子树内的每个节点连边,因为不管怎么连重心都不会变 显然是错的, ...
- window.setInterval
window.clearInterval与window.setInterval的用法 window.setInterval() 功能:按照指定的周期(以毫秒计)来调用函数或计算表达式. 语法:setI ...
- C# 常用类库说明
Array类 用括号声明数组是C#中使用Array类的记号.在后台使用C#语法,会创建一个派生于抽象基类Array的新类.这样,就可以使用Array类为每个C#数组定义的方法和属性了. Array类实 ...
- 配置lombok到eclipse上去
使用maven导入lombok.jar包,可以帮助我们省略掉getter/setting方法. 1.pom.xml 添加依赖: <dependency> <groupId>or ...
- 初识JavaScript对象
JavaScript对象语法.类型.属性 属性描述符(getOwnPropertyDescriptor().defineProperty()) [[Get]].[[Put]].Getter.Sette ...
- yii2 response多次输出问题的查找
{ "IsSuccess": 1, "ErrMsg": "OK", "Data": { "IsSuccess& ...
- 通过Callable接口实现多线程
一.通过Callable接口实现多线程 c.实现Callable重写call方法 实现Callable和实现Runnable类似,但是功能更强大,具体表现在 a.可以在任务结束后提供一个返回值,Run ...
- Java学习笔记【八、数据结构】
参考资料: http://www.cnblogs.com/janneystory/p/5758958.html array arraylist list linklist的区别 http://www. ...