Maven浅谈
- 预备知识:Maven概述
-
- Maven 是什么/li>
- Maven下载
- Maven的目标
- Maven POM
- 预备知识:Maven安装
-
- 配置环境变量
- Maven 仓库
-
- 配置本地仓库
- 配置中央仓库
- Maven知识点
-
- Maven 目录结构
- Maven 构建生命周期
-
- Clean 生命周期
- default 生命周期
- Site 生命周期
- 坐标
- 依赖
-
- 传递性依赖
- 依赖管理
- 依赖范围
- maven 常用命令
预备知识:Maven概述
Maven 是什么/h2>
Maven是Apache推出的一个软件项目管理和综合工具。基于项目对象模型(pom)的概念,Maven可以从一个中心资料片管理项目构建, 告和文件。Maven提供开发人员构建一个完整的生命周期框架。开发团队可以自动化完成项目的基础管理工具建设,Maven使用标准的目录结构和默认构建生命周期。Maven可以设置按标准在非常短的时间内完成配置工作,大部分的项目设置比较简单,并且可重复使用,Maven让开发人员的工作更加轻松,同时创建 表,检查,构建和测试自动化设置。概括来讲,Maven起到了简化和标准项目建设过程的作用。处理编译,分配,文档,团队协作和其他人物的无缝连接。Maven增加可重用性并负责建立相关的任务。
Maven下载
简单讲一下Maven我们如何下载,地址https://maven.apache.org/download.cgi
Maven的目标
Maven主要是提供给开发人员:
- List item 项目可复用,易维护,更容易理解一个综合模型;
- 插件或交互的工具,声明性模式;
Maven项目的机构和内容在一个xml文件中声明,pom.xml项目对象模型(pom),这是整个Maven项目系统的基本单元。Maven最强大的功能就是能够自动下载项目依赖库。
Maven POM
POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
执行任务或目标时,Maven 会在当前目录中查找 POM。它读取 POM,获取所需的配置信息,然后执行目标。
所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。
POM 中可以指定以下配置:
节点 | 描述 |
---|---|
project | 工程的根标签 |
modelversion | 模型版本需要设置为4.0 |
groupId | 这是工程组的标识。它在一个组织或者项目中通常是唯一的。例如,一个银行组织 com.companyname.project-group 拥有所有的和银行相关的项目。 |
artifactId | 这是工程的标识。它通常是工程的名称。例如,消费者银行。groupId 和 artifactId 一起定义了 artifact 在仓库中的位置 |
version | 这是工程的版本 。在 artifact 的仓库中,它用来区分不同的版本。例如:com.company.bank:consumer-banking:1.0com.company.bank:consumer-banking:1.1 |
预备知识:Maven安装
配置环境变量
-
右键 “计算机”,选择 “属性”,之后点击 “高级系统设置”,点击”环境变量”,来设置环境变量,有以下系统变量需要配置:
新建系统变量 MAVEN_HOME,变量值:E:Mavenapache-maven-3.3.9(文件夹所在目录)
-
完成上述操作后,cmd输入命令:mvn -version验证
出现如图表示成功:
Maven 构建生命周期
Maven 构建生命周期定义了一个项目构建跟发布的过程。
一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:
当一个阶段通过 Maven 命令调用时,例如 mvn compile,只有该阶段之前以及包括该阶段在内的所有阶段会被执行。
不同的 maven 目标将根据打包的类型(JAR / WAR / EAR),被绑定到不同的 Maven 生命周期阶段。
Site 生命周期
Maven Site 插件一般用来创建新的 告文档、部署站点等。
- pre-site:执行一些需要在生成站点文档之前完成的工作
- site:生成项目的站点文档
- post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy:将生成的站点文档部署到特定的服务器上
这里经常用到的是site阶段和site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看
坐标
Maven的一个核心的作用就是管理项目的依赖,引入我们所需的各种jar包等。为了能自动化的解析任何一个Java构件,Maven必须将这些Jar包或者其他资源进行唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标。包括我们自己开发的项目,也是要通过坐标进行唯一标识的,这样才能才其它项目中进行依赖引用。
Maven坐标为各种构件引入了秩序,任何一个构件都必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,他们是groupId、artifactId、version、packaging、classifier。先看一组坐标定义,如下:这是nexus-indexer的坐标定义,nexus-indexer是一个对Maven仓库编篡索引并提供搜索的类库,他是Nexus项目的一个子模块。上述代码片段中,其坐标分别为groupId:org.sonatype.nexus、artifactId:nexus-indexer、version:2.0.0.、packaging:jar,没有classifier。下面详细解释一下各个坐标元素。
groupId
定义当前Maven项目隶属的实际项目。首先,Maven项目和实际项目不一定是一对一的关系。比如SpringFramework这一实际项目,其对应的Maven项目会有很多,如spring-core、spring-context等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupId不应该对应项目隶属的组织或公司。原因很简单,一个组织下会有很多实际项目,如果groupId只定义到组织级别,而后面我们会看到,artifactId只能定义Maven项目(模块),那么实际项目这个层将难以定义。最后,groupId的表示方式与Java包名的表示方法类似,通常与域名反向一一对应。上例中,groupId为org.sonatype.nexus,org.sonatype表示Sonatype公司建立的一个非营利性组织,nexus表示Nexus这一实际项目,该groupId与域名nexus.sonatype.org对应。artifactId
该元素定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。比如上例中的artifactId是nexus-indexer,使用了实际项目名nexus作为前缀,这样做的好处是方便寻找实际构件。在默认情况下,Maven生成的构件,其文件名会以artifactId作为开头,如nexus-indexer-2.0.0.jar,使用实际项目名称作为前缀之后,就能方便从一个lib文件夹中找到某个项目的一组构件。考虑有5个项目,每个项目都有一个core模块,如果没有前缀,我们会看到很多core-1.2.jar这样的文件,加上实际项目名前缀之后,便能很容易区分foo-core-1.2.jar、bar-core-1.2.jarversion
该元素定义Maven项目当前所处的版本,如上例中nexus-indexer的版本是2.0.0。需要注意的是,Maven定义了一套完成的版本规范,以及快照(SNAPSHOT)的概念。packaging
该元素定义Maven项目的打包方式。首先,打包方式通常与所生成构件的文件扩展名对应,如上例中packaging为jar,最终的文件名为nexus-indexer-2.0.0.jar,而使用war打包方式的Maven项目,最终生成的构件会有一个.war文件,不过这不是绝对的。其次,打包方式会影响到构建的生命周期,比如jar打包和war打包会使用不同的命令。最后,当不定义packaging的时候,Maven会使用默认值jar。classifier
该元素用来帮助定义构建输出的一些附属构建。附属构件与主构件对应,如上例中的主构件是nexus-indexer-2.0.0.jar,该项目可能还会通过使用一些插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar这样一些附属构建,其包含了Java文档和源代码。这时候,javadoc和sources就是这两个附属构建的classifier。这样,附属构建也就拥有了自己唯一的坐标。还有一个关于classifier的典型例子是TestNG,TestNG的主构件是基于Java1.4平台的,而他又提供了一个classifier为jdk5的附属构件。注意,不能直接定义项目的classifier,因为附属构建不是项目直接默认生成地,而是由附加的插件帮助生成。上述5个元素中,groupId、artifactId、version是必须定义的,packaging是可选的(默认为jar),而classifier是不能直接定义的。
同时,项目构建的文件名和坐标相对应的,一般的规则为artifactId-version [-classifier] .packaging,[-classifier]表示可选。比如上例nexus-indexer的主构件为nexus-indexer-2.0.0.jar,附属构建有nexus-indexer-2.0.0-javaodc.jar。这里还要强调一点是,packaging 并非一定与构件扩展名对应,比如packaging为maven-plugin的构件扩展名为jar。
此外,Maven仓库的布局也是基于Maven坐标。
依赖
传递性依赖
传递性依赖是Maven2.0的新特性。假设你的项目依赖于一个库,而这个库又依赖于其他库。你不必自己去找出所有这些依赖,你只需要加上你直接依赖的库,Maven会隐式的把这些库间接依赖的库也加入到你的项目中。这个特性是靠解析从远程仓库中获取的依赖库的项目文件实现的。一般的,这些项目的所有依赖都会加入到项目中,或者从父项目继承,或者通过传递性依赖。
- 依赖调解
当项目中出现多个版本构件依赖的情形,依赖调解决定最终应该使用哪个版本。Maven 2.0只支持“短路径优先”原则,意思是项目会选择依赖关系树中路径最短的版本作为依赖。当然,你也可以在项目POM文件中显式指定使用哪个版本。在Maven2.0.8及之前的版本中,当两个版本的依赖路径长度一致时,哪个依赖会被使用是不确定的。不过从Maven 2.0.9开始,POM中依赖声明的顺序决定了哪个版本会被使用,也叫作”第一声明原则”。
“短路径优先”意味着项目依赖关系树中路径最短的版本会被使用。- 例如,假设A、B、C之间的依赖关系是A->B->C->D(2.0)和A->E->(D1.0),那么D(1.0)会被使用,因为A通过E到D的路径更短。
但如果你想要强制使用D(2.0),那你也可以在A中显式声明对D(2.0)的依赖。
- 例如,假设A、B、C之间的依赖关系是A->B->C->D(2.0)和A->E->(D1.0),那么D(1.0)会被使用,因为A通过E到D的路径更短。
- 排除依赖 – 如果项目X依赖于项目Y,项目Y又依赖项目Z,项目X的所有者可以使用”exclusion”元素来显式排除项目Z。
- 可选依赖 – 如果项目Y依赖项目Z,项目Y的所有者可以使用”optional”元素来指定项目Z作为X的可选依赖。那么当项目X依赖项目Y时,X只依赖Y并不依赖Y的可选依赖Z。项目X的所有者也可以根据自己的意愿显式指定X对Z的依赖。(你可以把可选依赖理解为默认排除)。
依赖管理
- 假设你有许多项目继承自同一个公有的父项目,那可以把所有依赖信息放在一个公共的POM文件,并且在子POM中简单第引用该构件即可。
注意:在这两个POM文件的依赖中,我们必须指定元素。因为与依赖管理元素匹配的依赖引用最小信息集是{groupId, artifactId, type, classfier}。许多情况下,依赖指向的jar不需要指定classfier。因为默认type是jar,默认classfiler为空,所以我们可以把信息集设置为{groupId, artifactId}。
- 依赖管理元素第二个非常有用的功能是控制传递性依赖中构件的版本
依赖范围
Maven有以下6种依赖范围:
- compile 这是默认范围。如果没有指定,就会使用该依赖范围。编译依赖对项目所有的classpath都可用。此外,编译依赖会传递到依赖的项目。
- provided 和compile范围很类似,但provided范围表明你希望由JDK或者某个容器提供运行时依赖。例如,当使用Java EE构建一个web应用时,你会设置对Servlet API和相关的Java EE APIs的依赖范围为provided,因为web容器提供了运行时的依赖。provided依赖只对编译和测试classpath有效,并且不能传递。
- runtime runtime范围表明编译时不需要依赖,而只在运行时依赖。此依赖范围对运行和测试classpath有效,对编译classpath无效。
- test test范围表明使用此依赖范围的依赖,只在编译测试代码和运行测试的时候需要,应用的正常运行不需要此类依赖。
- system 系统范围与provided类似,不过你必须显式指定一个本地系统路径的JAR,此类依赖应该一直有效,Maven也不会去仓库中寻找它。
- import(Maven2.0.9及以上)import范围只适用于pom文件中的部分。表明指定的POM必须使用部分的依赖。因为依赖已经被替换,所以使用import范围的依赖并不影响依赖传递。
依赖范围**(scope)** 编译时依赖 测试时依赖 运行时依赖 是否打入包 例子 compile Y Y Y Y SLF4J provided Y Y Y N SERVLET-API test N Y N N JUNIT runtime N Y Y Y MYSQL JDBC DRIVER system Y Y Y Y 有nexus后,不用system maven 常用命令
- 创建Maven的普通java项目:
- 创建Maven的Web项目:
- 编译源代码: mvn compile
- 编译测试代码:mvn test-compile
- 运行测试:mvn test
- 产生site:mvn site
- 打包:mvn package
- 在本地Repository中安装jar:mvn install
- 清除产生的项目:mvn clean
- 生成eclipse项目:mvn eclipse:eclipse
- 生成idea项目:mvn idea:idea
- 组合使用goal命令,如只打包不测试:mvn -Dtest package
- 编译测试的内容:mvn test-compile
- 只打jar包: mvn jar:jar
- 只测试而不编译,也不测试编译:mvn test -skipping compile -skipping test-compile
( -skipping 的灵活运用,当然也可以用于其他组合命令) - 清除eclipse的一些系统设置:mvn eclipse:clean
ps:
一般使用情况是这样,首先通过cvs或svn下载代码到本机,然后执行mvn eclipse:eclipse生成ecllipse项目文件,然后导入到eclipse就行了;修改代码后执行mvn compile或mvn test检验,也可以下载eclipse的maven插件。mvn -version/-v 显示版本信息
mvn archetype:generate 创建mvn项目
mvn archetype:create -DgroupId=com.oreilly -DartifactId=my-app 创建mvn项目mvn package 生成target目录,编译、测试代码,生成测试 告,生成jar/war文件
mvn jetty:run 运行项目于jetty上,
mvn compile 编译
mvn test 编译并测试
mvn clean 清空生成的文件
mvn site 生成项目相关信息的 站
mvn -Dwtpversion=1.0 eclipse:eclipse 生成Wtp插件的Web项目
mvn -Dwtpversion=1.0 eclipse:clean 清除Eclipse项目的配置信息(Web项目)mvn -DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。
mvn -Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。
mvn eclipse:eclipse 将项目转化为Eclipse项目在应用程序用使用多个存储库
发布第三方Jar到本地库中:
mvn -e 显示详细错误 信息.
mvn -U 强制更新依赖包
mvn -B 该参数表示让Maven使用批处理模式构建项目
mvn validate 验证工程是否正确,所有需要的资源是否可用。
mvn test-compile 编译项目测试代码。 。
mvn integration-test 在集成测试可以运行的环境中处理和发布包。
mvn verify 运行任何检查,验证包是否有效且达到质量标准。
mvn generate-sources 产生应用需要的任何额外的源代码,如xdoclet。常用命令总结:
mvn -v 显示版本
mvn help:describe -Dplugin=help 使用 help 插件的 describe 目标来输出 Maven Help 插件的信息。
mvn help:describe -Dplugin=help -Dfull 使用Help 插件输出完整的带有参数的目标列
mvn help:describe -Dplugin=compiler -Dmojo=compile -Dfull 获取单个目标的信息,设置 mojo 参数和 plugin 参数。此命令列出了Compiler 插件的compile 目标的所有信息
mvn help:describe -Dplugin=exec -Dfull 列出所有 Maven Exec 插件可用的目标
mvn help:effective-pom 看这个“有效的 (effective)”POM,它暴露了 Maven的默认设置mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook 创建Maven的普通java项目,在命令行使用Maven Archetype 插件
mvn exec:java -Dexec.mainClass=org.sonatype.mavenbook.weather.Main Exec 插件让我们能够在不往 classpath 载入适当的依赖的情况下,运行这个程序
mvn dependency:resolve 打印出已解决依赖的列表
mvn dependency:tree 打印整个依赖树mvn install -X 想要查看完整的依赖踪迹,包含那些因为冲突或者其它原因而被拒绝引入的构件,打开 Maven 的调试标记运行
mvn install -Dmaven.test.skip=true 给任何目标添加maven.test.skip 属性就能跳过测试
m声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!