Maven初步
Maven初入
maven 是一个项目管理工具, 它包含了一个 项目对象模型(Project Object Model POM), 一组标准集合, 一个项目生命周期(Project Lifecycle), 一个依赖管理系统(Dependency Management System), 和用来运行 定义在 生命周期阶段中插件目标的逻辑.
Maven的核心只做一些基础的事情, 解析XML文档, 管理生命周期, 插件, 仅此而已; Maven的主要职责是委派给各种各样的插件, 如编译源码, 打包二进制代码, 发布站点 和 其他构建任务, 而插件从 maven仓库获得.
文档参考自: Maven权威指南
Maven初步
安装自不必赘述, Maven的相关配置在 ~/.m2/settings.xml,
~/.m2/repository 是本地仓库目录.
maven核心概念
插件和目标
就像在前面所提到过的, Maven的核心所做的工作很少, 大部分工作都会叫给插件来做, 一个插件 是一个或多个目标的集合, 插件的直观表现就是一个或多个jar包, 目标指的就是 某一个具体的方法, 可以配置相应的参数, 同时需要给定一部分必须参数;
简写: pluginId:goalId
生命周期(Lifecycle)
生命周期是包含在一个项目中一系列有序的阶段, 在maven中配有默认的生命周期, 以验证项目的基本完整性开始, 以把项目发布成产品结束.
其中, 插件目标是可以附着在生命周期上的, 会随着生命周期的阶段 一步步执行, 当 maven执行一个阶段的时候, 他首先会有序执行前面的所有阶段, 并执行绑定在阶段上的默认目标, 到命令指定的那个阶段为止;
recourses: recourses; Recourses插件的 recourses目标绑定在了 recourses阶段, 这个目标复制 src/main/recourses 下的所有资源 和 其他任何配置的资源目录, 到输出目录;
compiler: compile 绑定到了 compile阶段,编译 src/main/java 下的所有源代码 和 其他任何配置的资源目录, 到输出目录.
recourses: testRecourses Resources插件的 testRecourses目标绑定到了 test-recourses阶段, 对应 src/test/resources
compiler: testCompile 对应 src/test/java
surefire: test surefire插件的目标test 绑定到 test阶段, 这个目标运行所有的测试, 并创建那些 捕捉 详细测试结果的文件, 默认情况下, 如果有测试失败, 这个目标会终止
jar:jar 绑定到 package阶段, 把输出目录打包成 jar文件.
Maven 坐标
POM为项目命名, 提供了项目的一组唯一标识符(坐标), 并通过 依赖(dependencies), 父(parents) 和 先决条件(prerequisite) 来定义和其他项目的关系.
Maven定义了一组坐标, 他们可以用来标识一个项目, 一个依赖, 或者MavenPom里一个插件.
GroupId: 团体, 公司, 组织等其他, 就是java中的 com.company.project
artifactId: 项目标识
version: 版本号, 一般会通过加上 "SNAPSHOT"标记, 标识正在开发中.
packing(非必须): 默认为 jar, 项目打包后输出, war 表示web 项目.
同时需要注意的是: 在 artifactId中最好不要使用 "."
Maven仓库
路径为, 相对于仓库根目录:
/<groupId>/<artifactId>/<version>/<artifactId>-<version>.<packing>
Maven依赖
对于依赖, 目前只需要知道依赖具有传递性,即可.
Maven注意事项
优化, 降低依赖重复
上移共同的依赖至 dependencyManagement
如果多于一个项目依赖于一个特定的依赖, 就可以在 dependencyManagement中列出这个依赖, 父POM包含一个版本和一组排除配置, 在子POM中需要使用 groupId和artifactId引用这个依赖, 如果依赖已经在 dependencyManagement中列出, 子项目可以额忽略版本和排除配置;
<properties>
<hibernate.annotation.version>3.3.0</hibernate.annotation.version>
</properties>
通过这种方式将版本信息定义为 常量, 通过 ${ }引用变量
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotation</artifactId>
<version>${hibernate.hibernate.annotation.version}</version>
</dependency>
为兄弟项目使用内置的 version 和 groupId
使用相同的 groupId 和 ${project.version}.
上移共同的 plugin 至 pluginManagement
显示的声明依赖, 不要通过依赖传递性来引用 jar包
使用 Maven Denpendency插件优化:
通过 mvn dependency:analyze 对项目进行分析, 但增删依赖判断的先决条件是单元测试;
在 analyze中, 生命周期依次为:
recourses, compile, testRecourses, testCompile, analyze;会将执行中的错误, 未声明的 jar, 声明未使用的jar 种种体现出来.
而使用 mvn dependency:tree , 会列出项目中所有的直接和传递性依赖.
几个帮助插件
mvn help:active-profiles 列出当前构建中活动的 Profile
mvn help:effective-pom 显示当前构建的实际 pom
mvn help:effective-settings 打印实际的setting, 包含全局和用户级别的
mvn help:describe 描述插件的属性, 无需在项目目录下运行, 但必须提供插件的 groupId 和 artifactId
如: mvn help:describe -Dplugin=complier [Dmojo=compile] [-Dfull]
第二个参数表示插件中的某一个目标, 第三个参数为目标的所有信息, 同时在:
"-D<name>=<value>" 这种方式设定 调用 mvn 插件目标 ,传入目标中的参数中的 值. 需要注意的是, 这并非是 Maven的语法, 其实是 java 用来设置系统属性的方式.
Maven Pom
所有的 Maven POM 都继承自超级POM, 超级POM所处目录为: {Maven HOME}/lib/maven-model-builder-{Maven Version}.jar 内 org.apache.maven.model 下的 POM-4.0.0.xml.
文件主要定义了:
单独的远程仓库, https://repo.maven.apache.org/maven2
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
为核心插件提供了默认的版本
我们自己建立的 POM最顶层继承自 超级 POM, 其次是所有的 父级POM, 自上向下 会一层层 覆盖之前的默认配置, 通过 mvn help:effective 可以查看当前项目的有效pom.
下面就开始一步步看POM.xml文件中的配置:
version
<major version>.<minor version>.<incremental version>-<qualifier> 1.3.5-beta-01
其中1为主版本号, 3为次版本号, 5为增量版本号, beta-01为限定版本号(alpha 和 beta). 如果版本号符合规则要求, 则按照版本号来比较, 否则按照字符串规则来进行比较. 比如 a10 是 排在 a2前面的, 因此 a10属于旧版本, 但在我们的定义中, 却应该是相反的.
版本界限配置方式:
(loVersion, hiVersion) 不包含
[loVersion, hiVersion] 包含<version>[3.8, 4.1.2]</version>
当不指定上界/下界时, 则为以上/以下
SNAPSHOT
如果你在版本中使用了 字符串 SNAPSHOT, 表示项目正处于 活动的 开发状态, Maven会在安装 或部署的时候将 符号展开为 一个时间和日期,转换为 UTC.(也就是快照版本)
如在创建的时候, 默认为 0.1-SNAPSHOT, 而后将项目部署到了 Maven仓库, Maven会将版本展开为 0.1-YYYYMMDD-HH24MISS-1, 这里的时间 为UTC时间.
如果项目依赖的一个组件正处于开发过程中, 依赖它的 SNAPSHOT版本, 则在运行构建的时候, 会自动从仓库下载最新的 SNAPSHOT, 同时, 要依赖 SNAPSHOT版本, 用户必须在 POM中使用 repository 和 pluginRepository 开启下载 SNAPSHOT功能.
<!--选择对应的 坐标, 将 enabled 属性设置为 true 即可-->
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories> <pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
而发布到 非 snapshot的 Maven仓库的构建不能依赖于 SNAPSHOT版本, 仅用于开发过程.
LATEST 和 RELEASE
当依赖于一个插件 或 依赖, 可以使用特殊值:
LATEST: 最新发布的版本 或 快照版.
RELEASE: 仓库中 最后一个非快照版本.
在项目发布的时候, 尽量不要使用 这三个关键字, 仅在开发时使用
变量引用
在Maven中有三个内置隐士变量:
env: 表示 environment, 系统的环境变量, 如 ${env.PATH}, 需要注意的是需要大写, 如 ${env.JAVA_HOME}
settings: 这个指的是 settings.xml中的属性, 但一直引用不成功.
project: 引用当前 project中的属性 如 ${project.artifactId}.
${basedir}, 可以访问当前项目根目录
Java系统属性
凡是可以被 java.lang.System 中的 getProperties()方法访问的属性
可以在Java中通过 System.getProperties().list(System.out); 在Maven中通过 ${} 直接访问, 如 ${java.runtime.name}
自定义属性:
<properties>
<attribute>value</attribute>
</properties>
访问方式即: ${attribute.value}
依赖范围
<version>1.0</version>
<scope>test</scope>
compile: 编译范围, 默认范围, 在所有的classpath都可以使用, 也会被打包
provided: 已提供范围, 只有当 JDK/容器已经提供该依赖之后才使用, 如在 开发中 需要 Servlet API编译一个 Servlet, 但在打包发布之后这部分应该由 容器/服务器本身来提供. 仅在编译时可用. 不可传递, 不会打包.
runtime: 运行时范围, 在编译时不需要, 在运行时需要.
test: 测试范围, 仅在测试时需要, 测试运行, 测试编译.
system: 系统范围, 必须提供 systemPath, 即本地jar文件的路径.
可选依赖:
<version>1.0</version>
<optional>true</optional>
通过这种方式生命的依赖, 不会被传递. 需要在子项目中再度生命
依赖的传递
test范围不会被传递, provided范围 仅在 provided中被传递, runtime 和 compile 在 四种范围都会被传递.
e.g. : A 包含对 B的测试范围依赖, B 包含对 C的编译时依赖, 则 C为A的测试范围依赖
A:
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
B:
<dependency>
<groupId>C</groupId>
<artifactId>C</artifactId>
<version>1.0</version>
</dependency>
e.g. : A包含对 B的测试范围依赖, B包含对C的测试范围依赖, 则 A与C无关.
A:
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
B:
<dependency>
<groupId>C</groupId>
<artifactId>C</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
依赖追踪:
在 Maven中, 如果多个项目依赖于同一个 project, 则Maven会找到 所有依赖中版本最新的 依赖, 作为最终的选择, 所以可以排除对应的依赖, 且同时 可以 更换自己想要的版本.
e.g.:
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>C</groupId>
<artifactId>C</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖管理
这在之前 优化 已经提到, 采取在父级项目中定义 dependencyManagement, pluginManagement, 在子级中沿用父级的版本, 仅需要列出所选取的 依赖坐标, 而无需再度定义版本(如果定义子级版本, 父级就会被忽略);
多模块项目:
<modules>
<module>project-a</module>
<module>project-b</module>
</modules>
多模块项目的打包总是一个 POM 而非构建, 其中各个模块可以为 POM 或者 jar
项目继承:
<parent>
<groupId>C</groupId>
<artifactId>C</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
可以被继承的项目:
- 定义符: groupId 和 artifactId 必须有一个被重写, 不能有完全相同的坐标.
- 依赖
- 开发者和贡献者
- 插件列表
- 报告列表
- 插件执行
- 插件配置
继承中, 当 父级 POM 在 父目录../pom.xml 或者 在 本地仓库目录时 可用, 否则的话需要指明 父级POM的相对位置.
<parent>
<groupId>C</groupId>
<artifactId>C</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../a-parent/pom.xml</relativePath>
</parent>
暂时告一段落.
Maven初步的更多相关文章
- Maven初步接触
最近随着搜资料,网上这样的字眼越来越多,我了解到这是构建项目的一种方式,于是准备简单看一下 首先粘几篇文章,作为学习的初步资料 Maven入门 http://blog.csdn.net/prstaxy ...
- (一)Maven初步了解与认识
Apache Maven是一个软件项目管理的综合工具.基于项目对象模型(POM)的概念,提供了帮助管理构建.文档.报告.依赖.发布等方法,Maven简化和标准化项目建设过程.处理编译,分配,文档,团队 ...
- Maven初步搭建 (一)
什么是maven? 也许很多人开始的时候跟我一样,在看了很多工程之后都不知道这个鸟东西到底是用来干嘛用的!:-D 一个东西之所以会出现是有其原因的,譬如Linus大神写git. Maven项目对象模型 ...
- maven初步入门demo
Maven是跨平台的项目管理工具.作为Apache组织中的一个颇为成功的开源项目,主要服务于基于java平台的项目构建.依赖管理和项目信息管理. maven本身使用java开发而成,所以使用前确保电脑 ...
- SSH深度历险(四) Maven初步学习
这几天接触这个词,很多遍了,只是浅显的体会到它在GXPT中的好处,功能之强大,又通过网络查询了资料进一步的认识学习了,和大家分享. Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理 ...
- Maven初步踩坑
2015-02-08 今天创建maven项目,要从中央仓库下载一堆包到本地仓库,等了好久.结果下好了之后,maven项目上有个感叹号,也没有发现代码里哪配置有错误. 和实验室好多小伙伴一起交流 也没找 ...
- SSH深度历险(四) Maven初步学�
这几天接触这个词,非常多遍了,仅仅是浅显的体会到它在GXPT中的优点,功能之强大,又通过网络查询了资料进一步的认识学习了,和大家分享. Maven是基于项目对象模型(POM),能够通过一小段描写叙述信 ...
- maven初步了解
目标:创建一个父maven项目,有两个子项目分别为serverCenter,dbConnector. 建议:全程不要导入Jar包,全部使用maven依赖的方式导入包. 1.创建maven项目 这个创建 ...
- 关于Maven的安装及初步使用
关于Maven的初步使用 1. 下载: 进入http://maven.apache.org/download.cgi下载 Maven 3.3.1 2. 将压缩包解压到自己的硬盘中,最好放在某个盘 ...
随机推荐
- Oracle之 11gR2 RAC 修改监听器端口号的步骤
Oracle 11gR2 RAC 修改监听器端口号的步骤 说明:192.168.188.181 为public ip1192.168.188.182 为public ip2192.168.188.18 ...
- iframe标签里面的页面元素只读
iframe标签里面的页面元素只读,可以通过设置一个只读的透明div进行遮罩实现. html代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...
- ThinkPHP3.2中英文切换!
小伙伴们好久不见!!! 最近公司项目版本升级,小梦已经忙成了狗,无暇顾及文章,今天抽时间写一篇助助兴! 用Thinkphp这个国产框架已经2年多了,现在有一个小功能:网站中英文切换功能,当然这 ...
- JavaScript call()和apply()
ECMAScript规范给所有函数都定义了call()与apply()两个方法,call()与apply()的第一个参数都是需要调用的函数对象,在函数体内这个参数就是this的值,剩余的参数是需要传递 ...
- Python 操作 GA API 指南
因为需要写一个 Blog Feature 的缘故,所以接触了下 GA 的 Python API,发现 G 家的 API 不是那么直观,比较绕,但是,在使用过程中发现其实 G 家的 API 设计挺有意思 ...
- HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)
逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K= ...
- UVA 572 dfs求连通块
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...
- c语言基础学习07_关于指针的复习
============================================================================= 指针变量之间赋值是需要兼容的. 例如:int ...
- Django 用散列隐藏数据库中主键ID
最近看到了一篇讲Django性能测试和优化的文章, 文中除了提到了很多有用的优化方法, 演示程序的数据库模型写法我觉得也很值得参考, 在这单独记录下. 原文的演示代码有些问题, 我改进了下, 这里可以 ...