一、使用入门
1.1.基本概念
maven 是一个项目管理和整合工具。Maven 为开发者提供了一套完整的构建生命周期框架。开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置,因为 Maven 使用了一个标准的目录结构和一个默认的构建生命周期。在有多个开发团队环境的情况下,Maven 能够在很短的时间内使得每项工作都按照标准进行。因为大部分的工程配置操作都非常简单并且可复用,在创建报告、检查、构建和测试自动配置时,Maven 可以让开发者的工作变得更简单。
1.2.命令语法
1.2.1.Mvn命令格式
# 1.执行plugin-name插件的goal-name目标
>mvn [plugin-name]:[goal-name]
# 2.运行指定插件的指定目标
>mvn dependency:tree| tomcat:run
# 3.运行生命周期阶段
>mvn clean|compile|package|install|deploy|site|test
1.2.2.Mvn命令参数
# 1.-D 传入属性参数
#如:将maven.test.skip设置为true
>mvn package –Dmaven.test.skip=true
# 2.-P 使用指定的Profile
#如:打开发环境的包
>mvn package –P dev
1.2.3.Mvn常用命令
# 清理
>mvn clean
# 编译主程序
>mvn compile
# 打包
>mvn package
# 安装jar到本地库
>mvn install
>mvn clean package deploy
1.3.POM 的结构
<project>
< parent/>
<modelVersion/>
<!--坐标 -->
groupId/><artifactId/><version/>
< modules/>
< dependencies />
< build>
<pluginManagement>
<plugins>
< plugin >
<!--坐标 -->
<groupId/><artifactId/><version/>
<configuration>
< archive>
< manifest>
< mainClass/>
< manifest/>
< archive/>
<configuration/>
< plugin />
<plugins/>
<pluginManagement/>
< build/>
< properties />
<!--远程仓库 -->
< distributionManagement/>
<!--默认依赖信息 -->
< dependencyManagement/>
<!--连接代码库 -->
< scm/>
<!--环境激活文件 -->
<profiles/>
<project/>
1.4.Maven 打 Jar 包
1.4.1.原始 javac 方式打包
(1)指定入口方法类
项目文件夹META-INF下的文件MENIFEST.MF中配置好入口方法:Main-Class: com.test.Hello
(2)编译java文件到当前目录
javac -d . …/main/java/com/test/Hello.java
(3)打包
jar -cvfm hello.jar …/META-INF/MENIFEST.MF com
生成jar名 打包com下的所有class
(4)对 jar 包指定入口 main
此时的jar包是不可直接运行的,需要指定入口main类,进入META-INF目录,编辑MANIFEST.MF文件,手动添加如下:
Main-Class: Hello
(5)运行jar包
jar -jar hello.jar
1.4.2.Maven 方式打包
(1)在pom文件内配置入口类
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!--这里指定入口main类 -->
<mainClass>com.test.Hello</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
(2)执行maven打包,依次输入报名和版本号
mvn package
(3)运行jar包
java -jar target/hello-1.0.jar
二、构建过程
清理 -> 编译 -> 测试 -> 报告 -> 打包
三、生命周期
Mvn命令:
- 三个生命周期完全独立,maven 只定义生命周期,具体的执行交由 plugin 插件来完成
- 运行任何一个阶段,其前面的所有阶段都会被运行,如:mvn install,会 default 引一阶段运行到 install 阶段
运行任何一个阶段,都会从其所在生命周期的第一个阶段开始,顺序执行到指定的阶段,如:
mvn package — 本义:执行default周期的 package 阶段,maven 会自动从 process-resources 阶段开始运行到 package 阶段结束。
四、依赖传递与冲突
4.1.jar 的依赖传递
(1)路径最短原则:product和customer里的引用路径较短。
(2)同路径长度下,谁先声明谁优先:看product依赖和customer依赖在pom中声明位置,谁先用谁的。
(3)使用exclusions排除。
4.2.jar 的依赖冲突
4.2.1.查看冲突方式
(1)利用idea插件直接查看依赖关系。
(2)命令方式查看依赖树:>mvn dependency:tree。
4.2.2.解决冲突方式
(1)使用标签
<exclusions>
<exclusion>
<artifactId><artifactId/>
<groupId><groupId/>
<exclusion/>
<exclusions/>
(2)声明依赖范围
<scope>范围参数<scope/>
范围参数 | 作用 |
---|---|
compile | 默认范围,用于编译依赖的jar在打包时会包含进去 |
provided | 类似于编译,但支持你期待jdk或者容器提供,类似于classpath 依赖的jar在打包时不会包含进去 |
runtime | 在执行时需要使用,依赖的jar在打包时会包含进去 |
test | test任务时使用,依赖的jar在打包时不会包含进去 |
system | 需要外在提供相应的元素。通过systemPath来取得 , 一般禁止使用 |
注:每个scope实际上是配置了一个不同的classpath,jvm根据选择不同的classpath来达到依赖不同。
五、标签解析
<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/maven-v4_0_0.xsd ">
<!-- 父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。
坐标包括group ID,artifact ID和 version。 -->
<parent>
<!-- 被继承的父项目的构件标识符 -->
<artifactId>xxx</artifactId>
<!-- 被继承的父项目的全球唯一标识符 -->
<groupId>xxx</groupId>
<!-- 被继承的父项目的版本 -->
<version>xxx</version>
<!-- 父项目的pom.xml文件的相对路径。相对路径允许你选择一个不同的路径。默认值是../pom.xml。
Maven首先在构建当前项目的地方寻找父项目的pom,其次在文件系统的这个位置(relativePath位置),
然后在本地仓库,最后在远程仓库寻找父项目的pom。 -->
<relativePath>xxx</relativePath>
</parent>
<!-- 声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,
这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。 -->
<modelVersion> 4.0.0 </modelVersion>
<!-- 项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成,
如com.mycompany.app生成的相对路径为:/com/mycompany/app -->
<groupId>xxx</groupId>
<!-- 构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID
和groupID;在某个特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven
为项目产生的构件包括:JARs,源码,二进制发布和WARs等。 -->
<artifactId>xxx</artifactId>
<!-- 项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型 -->
<packaging> jar </packaging>
<!-- 项目当前版本,格式为:主版本.次版本.增量版本-限定版本号 -->
<version> 1.0-SNAPSHOT </version>
<!-- 项目的名称, Maven产生的文档用 -->
<name> xxx-maven </name>
<!-- 项目主页的URL, Maven产生的文档用 -->
<url> http://maven.apache.org </url>
<!-- 项目的详细描述, Maven 产生的文档用。 当这个元素能够用HTML格式描述时(例如,CDATA中的文本会被解析器忽略,
就可以包含HTML标签), 不鼓励使用纯文本描述。如果你需要修改产生的web站点的索引页面,你应该修改你自己的
索引页文件,而不是调整这里的文档。 -->
<description> A maven project to study maven. </description>
<!-- 描述了这个项目构建环境中的前提条件。 -->
<prerequisites>
<!-- 构建该项目或使用该插件所需要的Maven的最低版本 -->
<maven></maven>
</prerequisites>
<!-- 项目的问题管理系统(Bugzilla, Jira, Scarab,或任何你喜欢的问题管理系统)的名称和URL,本例为 jira -->
<issueManagement>
<!-- 问题管理系统(例如jira)的名字, -->
<system> jira </system>
<!-- 该项目使用的问题管理系统的URL -->
<url> http://jira.baidu.com/banseon </url>
</issueManagement>
<!-- 项目持续集成信息 -->
<ciManagement>
<!-- 持续集成系统的名字,例如continuum -->
<system></system>
<!-- 该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。 -->
<url></url>
<!-- 构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告) -->
<notifiers>
<!-- 配置一种方式,当构建中断时,以该方式通知用户/开发者 -->
<notifier>
<!-- 传送通知的途径 -->
<type></type>
<!-- 发生错误时是否通知 -->
<sendOnError></sendOnError>
<!-- 构建失败时是否通知 -->
<sendOnFailure></sendOnFailure>
<!-- 构建成功时是否通知 -->
<sendOnSuccess></sendOnSuccess>
<!-- 发生警告时是否通知 -->
<sendOnWarning></sendOnWarning>
<!-- 不赞成使用。通知发送到哪里 -->
<address></address>
<!-- 扩展配置项 -->
<configuration></configuration>
</notifier>
</notifiers>
</ciManagement>
<!-- 项目创建年份,4位数字。当产生版权信息时需要使用这个值。 -->
<inceptionYear />
<!-- 项目相关邮件列表信息 -->
<mailingLists>
<!-- 该元素描述了项目相关的所有邮件列表。自动产生的网站引用这些信息。 -->
<mailingList>
<!-- 邮件的名称 -->
<name> Demo </name>
<!-- 发送邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<post> banseon@126.com </post>
<!-- 订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<subscribe> banseon@126.com </subscribe>
<!-- 取消订阅邮件的地址或链接,如果是邮件地址,创建文档时,mailto: 链接会被自动创建 -->
<unsubscribe> banseon@126.com </unsubscribe>
<!-- 你可以浏览邮件信息的URL -->
<archive> http:/hi.baidu.com/banseon/demo/dev/ </archive>
</mailingList>
</mailingLists>
<!-- 项目开发者列表 -->
<developers>
<!-- 某个项目开发者的信息 -->
<developer>
<!-- SCM里项目开发者的唯一标识符 -->
<id> HELLO WORLD </id>
<!-- 项目开发者的全名 -->
<name> banseon </name>
<!-- 项目开发者的email -->
<email> banseon@126.com </email>
<!-- 项目开发者的主页的URL -->
<url></url>
<!-- 项目开发者在项目中扮演的角色,角色元素描述了各种角色 -->
<roles>
<role> Project Manager </role>
<role> Architect </role>
</roles>
<!-- 项目开发者所属组织 -->
<organization> demo </organization>
<!-- 项目开发者所属组织的URL -->
<organizationUrl> http://hi.baidu.com/xxx </organizationUrl>
<!-- 项目开发者属性,如即时消息如何处理等 -->
<properties>
<dept> No </dept>
</properties>
<!-- 项目开发者所在时区, -11到12范围内的整数。 -->
<timezone> -5 </timezone>
</developer>
</developers>
<!-- 项目的其他贡献者列表 -->
<contributors>
<!-- 项目的其他贡献者。参见developers/developer元素 -->
<contributor>
<!-- 项目贡献者的全名 -->
<name></name>
<!-- 项目贡献者的email -->
<email></email>
<!-- 项目贡献者的主页的URL -->
<url></url>
<!-- 项目贡献者所属组织 -->
<organization></organization>
<!-- 项目贡献者所属组织的URL -->
<organizationUrl></organizationUrl>
<!-- 项目贡献者在项目中扮演的角色,角色元素描述了各种角色 -->
<roles>
<role> Project Manager </role>
<role> Architect </role>
</roles>
<!-- 项目贡献者所在时区, -11到12范围内的整数。 -->
<timezone></timezone>
<!-- 项目贡献者属性,如即时消息如何处理等 -->
<properties>
<dept> No </dept>
</properties>
</contributor>
</contributors>
<!-- 该元素描述了项目所有License列表。 应该只列出该项目的license列表,不要列出依赖项目的 license列表。
如果列出多个license,用户可以选择它们中的一个而不是接受所有license。 -->
<licenses>
<!-- 描述了项目的license,用于生成项目的web站点的license页面,其他一些报表和validation也会用到该元素。 -->
<license>
<!-- license用于法律上的名称 -->
<name> Apache 2 </name>
<!-- 官方的l