Maven笔记(一)
1. 坐标
Maven坐标为各种构件引入了秩序,任何一个构件都有必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,它们是groupId, artifactId, version, packaging, classifier。
下面简单介绍一下这几个标签
1) groupId
定义当前Maven项目隶属的实际项目,当然跟实际项目之间并不是一对一的关系。其命名方式与Java包名的方式类似,通常与域名反向一一对应。例如org.sonatyp.nexus。在后面的聚合里面可以看到,同一项目的不同模块,拥有相同的groupId
2)artifactId
定义实际项目中的一个Maven项目(或者模块),推荐的做法是使用实际项目名称作为artifactId的前缀,这样的作用是当不同的项目拥有同样的模块名称时方便区分,如foo-core-1.2.jar, bar-core-1.2.jar等。
3)version
定义Maven项目当前所处的版本,Maven定义了一整套版本规范,以及快照的概念。
上面三个元素是必须定义的
4)packaging
定义项目的打包方式,包括pom,war,jar等,默认为jar.
5)classifier
用来帮助定义构建输出的一些附属构件。附属构件与主构件对应,例如foo-core.1.2.jar,还可以通过插件的方式生成foo-core-1.2-javadoc.jar等。该标签不能直接定义,因为附属构件不是由项目直接默认生成的,而是由附加的插件生成。
2.依赖
pom.xml 根元素project下的dependencies可以配置一个或多个dependency元素,以声明一个或多个项目依赖。(何为依赖?其实就是引用……)
每个依赖可以包含的元素有:
1)groupId, artifactId, version。基本坐标,上面已描述
2)type 依赖的类型,对应构件的packaging.大部分情况下,该元素不必声明,默认值为jar.
3)scope 依赖的范围
首先要知道,Maven在编译项目主代码的时候,需要使用一套classpath(简称编译classpath);在编译和执行测试的时候会使用另外一套classpath(简称测试classpath);最后,在实际运行Maven项目时,又会使用另外一套classpath(简称运行classpath,其实不是很懂,运行期间还用到Maven么?)
依赖范围就是用来控制依赖与这三种classpath之间的关系的
compile:编译依赖范围,默认的范围,对于三种classpath都有效。
test:测试依赖范围,只对于测试classpath有效。
provided:已提供依赖范围,对于编译和测试classpath有效,在运行时无效。
runtime: 运行时依赖范围,对于测试和运行时classpath有效,在编译时无效。
system:系统依赖范围,该依赖与provided的范围一致,但其依赖必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此慎用。如下:
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
import:导入依赖范围。后续再介绍。
4)exclusions 排除传递性依赖
依赖是会传递的,例如A依赖了B,B依赖了C,那么A和C之间便是传递性依赖。如果A实际上不需要依赖,那么可以通过此项将两者之间的依赖切断。
依赖范围不仅可以控制依赖与三种classpath的关系,还可以对传递性依赖产生影响。
首先假设A依赖了B,B依赖了C,那么,A和B之间是第一直接依赖,B和C之间是第二直接依赖,A和C之间是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围。具体范围如下图,左边一列是第一直接依赖,上面一行为第二直接依赖
第一直接依赖| 第二直接依赖 compile test provided runtime
compile compile ---- ---- runtime
test test ---- ---- test
provided provided ---- provided provided
runtime runtime ---- ---- runtime
5)optional 依赖是否可选
A->B->X(可选), A->B->Y(可选),根据传递性,假如所有这几个依赖范围都是compile,那么X Y就是A的compile范围传递性依赖,然而,由于这里X Y都是可选的,依赖将不会传递,也就是说,X Y将不会对A造成影响。
3.依赖调解
依赖传递机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关系项目直接依赖是什么。
假设有如下场景:A->B->C->X(1.0) ,A->D->X(2.0),现在X有两个版本,那么哪个版本会被Maven解析呢?
Maven依赖调解第一原则是:路径最近者会被解析,那么上例中,X(1.0)将会被解析。
再考虑一个场景:A->B->X(1.0),A->D->X(2.0),依赖的路径都是2,哪个版本会被解析呢?
Maven依赖调解第二原则是:第一声明者优先。在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用。在这个例子中,在A的POM文件,如果B比D先声明,那么X(1.0)将被解析使用。
4.最佳实践
1)排除依赖,不赘述
2)归类依赖
假设项目中有很多对Spring Framework的依赖(org.springframework:spring-core:2.5.6, org.springframework:spring-beans:2.5.6等),这些依赖都是来自同一项目的不同模块,因此版本是相同的,可以预见未来如果要升级,那么版本号也是要一起升级的。
可以通过Maven属性,定义一些变量,统一使用,类似代码中的常量。使用类似EL表示式的变量形式。
<project>
......
<properties>
<springframework.version>2.5.6</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>......</groupId>
<artifactId>......</artifactId>
<version>${springframework.version}</version>
</dependency>
......
</dependencies>
3)优化依赖
mvn dependency:list 查看项目已解析的构件的列表

mvn dependency:tree 查看项目依赖的构件的依赖树

mvn dependency:analyze 分析项目对依赖的使用情况。主要是两部分
首先是Used undeclared dependencies,项目中使用到的但没有显式声明的依赖。看似没有任何问题,实际上也隐藏风险。例如A->B->X(1.0),A用到了X(1.0)的接口,却又不显式声明,那么当B的依赖升级变成X(2.0),可能接口变更,A就有可能编译失败。
其次是Unused declared dependencies,未使用的,却声明了的依赖。由于这个命令只会分析编译主代码和测试代码需要用到的依赖,一些执行测试和运行时需要的依赖它发现不了,所以不能草率删除,应进行分析。

Maven笔记(一)的更多相关文章
- maven笔记--持续更新
笔记: 在创建maven项目的时候,如果用到servlet的时候,需要导入包,这时候,需要导入本地仓库的jar包,即依赖包.语法如下 <dependency> <groupId> ...
- Maven笔记---超详细
显眼位置标注来源:此文章为B站课程黑马程序员Maven全套教程笔记,由本人整理. Maven简介 Maven的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM) POM (P ...
- maven笔记
jar间接依赖: 被依赖的jar的范围要设置成compile,因发布会包含test范围依赖的jar包. 建立项目之间的联系:先在pom中设定依赖关系,然后可以引用了 .conf: C ...
- Maven 笔记
maven DOS 打包命令:maven项目 cd 进入项目根目录执行 mav clean package;
- 框架Maven笔记系列 一 基础
主题:SpringMVC 学习资料参考网址: 1.http://www.icoolxue.com 2.http://maven.apache.org/ 1.Maven解决了什么问题? Maven基于项 ...
- maven笔记-入门(helloWorld)
maven: pom.xml:文件 groupId,artifactId,Version定义了一个项目的基本坐标 groupId:定义了项目属于哪个组,往往与项目所在的组织和公司有关 artifact ...
- Maven笔记(二)仓库
1.仓库布局 任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这就是Maven的仓库布局方式 路径与坐标的对应关系为:groupId/artifactId/version/ ...
- maven笔记学习
一.修改setting.xml文件中的镜像 在导入他人项目或者在导入项目时,我们会出现在项目中不能识别maven配置的库文件的情况那么我们可以重新下载本地库, 首先我们可以修改我们安装的maven环境 ...
- maven笔记-将本地jar包打包进可执行jar中
参考资料:http://www.cnblogs.com/richard-jing/archive/2013/01/27/Maven_localjar.html 使用本地jar <dependen ...
随机推荐
- [Swustoj 24] Max Area
Max Area 题目描述: 又是这道题,请不要惊讶,也许你已经见过了,那就请你再来做一遍吧.这可是wolf最骄傲的题目哦.在笛卡尔坐标系正半轴(x>=0,y>=0)上有n个点,给出了这些 ...
- apache开源项目--hadoop
Hadoop 是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系统(Had ...
- Warning: Function created with compilation errors!
解决方案: sqlplus / as sysdba grant execute on UTL_I18N to scott; grant execute on DBMS_CRYPTO to scott;
- Hibernate4搭建Log4J日志管理(附Log4j.properties配置详解)
1.首先加入slf4j的jar包,即slf4j-api-1.6.1.jar 在hibernate官网下载hibernate-release-4.2.2.Final.zip并解压,在hibernate- ...
- HDOJ-ACM1005(JAVA)
转载声明:原文转自http://www.cnblogs.com/xiezie/p/5502918.html JAVA语言实现: 拿到题目第一反应是简单地实现递归: import java.util.* ...
- Select the best path in a matrix
Amazon interview question: Given a 2-dimensional array with arbitrary sizes and contains random posi ...
- Block介绍(一)基础
一.概述 Block是C级别的语法和运行时特性.Block比较类似C函数,但是Block比之C函数,其灵活性体现在栈内存.堆内存的引用,我们甚至可以将一个Block作为参数传给其他的函数或者Block ...
- 关于JAVA中URL传递中文参数的问题
今天在调用一个接口时,需要传递一个中文参数,结果获取不到数据,原因就在于中文传参的编码问题. 问题来源:URL url= new URL("http://XXX?OrganName=司法厅& ...
- 换种眼光看Spring之bean是怎么诞生的(一)
Java的世界里处处存在了对象,有时候换一种眼光往往会给自己带来与之前大不一样的理解. 一个对象的出现离不开字节码,拿classforname来讲,classforname("...&quo ...
- Cactus借助Jetty测试Servlet
这是一个WebProject,但不需要web.xml,因为用不到它 首先是待测试的LoginServlet.java package com.jadyer.servlet; import java.i ...