摘要: Maven
菱农,坐標(biāo)
缭付,依賴
,依賴傳遞
循未,依賴范圍
Maven的一大功能是管理項(xiàng)目依賴
陷猫,為了能自動(dòng)化解析任何一個(gè)java構(gòu)建,Maven就必須將它們唯一標(biāo)識
的妖。Maven定義了一組規(guī)則绣檬,任何一個(gè)構(gòu)建都可以使用Maven坐標(biāo)位移標(biāo)識,自己開發(fā)的項(xiàng)目也要設(shè)置適當(dāng)?shù)淖鴺?biāo)嫂粟,其他項(xiàng)目才能引用該項(xiàng)目生成的構(gòu)建娇未。
坐標(biāo)詳解
坐標(biāo)元素包括groupId
,artifactId
星虹,version
零抬,packaging
,classifier
搁凸。其中g(shù)roupId媚值,artifactId,version是必須定義的护糖,packaging是可選的褥芒,classifier是不能直接定義的。項(xiàng)目構(gòu)建的文件名和坐標(biāo)對應(yīng)嫡良,一般規(guī)則為artifactId-version [-classifier] .packaging
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.3.0</version>
</dependency>
-
groupId
: 定義當(dāng)前Maven項(xiàng)目隸屬的實(shí)際項(xiàng)目
锰扶,Maven項(xiàng)目和實(shí)際項(xiàng)目不一定是一對一的關(guān)系,比如Spark實(shí)際項(xiàng)目會(huì)有很多Maven項(xiàng)目比如spark-core寝受,spark-sql坷牛,spark-mllib等,一個(gè)實(shí)際項(xiàng)目往往會(huì)被分為很多模塊
很澄。groupId不應(yīng)該對應(yīng)項(xiàng)目隸屬的組織或公司京闰,因?yàn)橐粋€(gè)組織或公司下有很多實(shí)際項(xiàng)目颜及。 -
artifactId
: 該元素定義實(shí)際項(xiàng)目中的一個(gè)Maven項(xiàng)目
(模塊),推薦的做法是使用實(shí)際項(xiàng)目
名稱作為artifactId的前綴
蹂楣,這樣方便尋找實(shí)際構(gòu)建俏站,因?yàn)槟J(rèn)情況下Maven生成的構(gòu)建會(huì)以artifactId作為開頭,如果采用實(shí)際項(xiàng)目作為前綴就很方便從lib文件夾中找到一組構(gòu)建痊土。另一方面如果不加實(shí)際項(xiàng)目名前綴肄扎,諸多名稱為core的模塊生成的構(gòu)建名字一樣。 -
version
: 該元素定義Maven項(xiàng)目當(dāng)前所處的版本
赁酝。 -
packaging
: 該元素定義Maven項(xiàng)目的打包方式
犯祠,如果不指定默認(rèn)就是jar
,打包方式通常與所生成的構(gòu)建的文件擴(kuò)展名
對應(yīng)酌呆。 -
classifier
: 該標(biāo)簽幫助定義構(gòu)建輸出一些附屬構(gòu)建
衡载。
依賴配置
根元素project
下dependencies
可以包含一個(gè)或者多個(gè)dependency
元素,每個(gè)元素內(nèi)聲明一個(gè)依賴
肪笋,每個(gè)依賴包含以下元素月劈。
<!--Spark 依賴 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>com.mycom</groupId>
<artifactId>auto-label</artifactId>
<scope>system</scope>
<systemPath>/home/myproject/auto-label-1.0.2.jar</systemPath>
<version>1.0.2</version>
</dependency>
- groupId,arifactId藤乙,version: 依賴的基本
坐標(biāo)
。 - type: 依賴類型惭墓,默認(rèn)是
jar
和packaging對應(yīng)坛梁。 - scope: 依賴范圍。
- exclusions: 用來
排除傳遞性依賴
腊凶。
依賴范圍
Maven需要三套classpath
划咐,分別在編譯
,測試
钧萍,運(yùn)行
的時(shí)候起作用褐缠,classpath就是jvm找到class文件的環(huán)境變量
。依賴范圍就是控制依賴和這三種classpath的關(guān)系风瘦,主要有以下幾種:
-
compile
:編譯
依賴范圍队魏,如果沒有指定默認(rèn)就是這個(gè)依賴范圍。對編譯万搔,測試胡桨,運(yùn)行三種classpath都有效。 -
test
:測試
依賴范圍瞬雹,只對測試classpath有效昧谊,在編譯和運(yùn)行的時(shí)候無法使用。 -
provided
: 已提供
依賴范圍酗捌,對編譯和測試有效呢诬,對運(yùn)行無效涌哲,在項(xiàng)目運(yùn)行時(shí)如果容器
已提供,就不需要Maven重復(fù)引用尚镰。 -
runtime
:運(yùn)行
時(shí)依賴范圍膛虫,對于測試和運(yùn)行有效,編譯無效钓猬。 -
system
:系統(tǒng)
依賴范圍稍刀,該依賴與三種classpath的關(guān)系,和provided依賴范圍完全一致敞曹。system需要通過systemPath
標(biāo)簽顯式指定依賴文件的路徑账月,這樣引入的依賴不是Maven倉庫解析的。
傳遞依賴
如果不使用Maven澳迫,對于項(xiàng)目依賴自身還需要其他依賴的情況局齿,只能報(bào)錯(cuò)classNotFound之后加入相關(guān)依賴,或者下載一個(gè)很大的依賴包都很麻煩橄登。Maven的傳遞性依賴
機(jī)制可以很好解決這個(gè)問題抓歼。如果項(xiàng)目A有一個(gè)B依賴,B自身有需要C依賴拢锹,則C是A的一個(gè)傳遞性依賴谣妻。
傳遞性依賴的依賴范圍
依賴范圍不僅可以控制依賴與三種classpath的關(guān)系,還對傳遞性依賴產(chǎn)生影響卒稳,如果A依賴B蹋半,B依賴C,則A對于B是第一直接依賴
充坑,B對于C是第二直接依賴
减江,A對于C是傳遞性依賴
。第一直接依賴的范圍和第二直接依賴的范圍決定了傳遞性依賴的范圍捻爷。
其中第一列代表第一直接依賴辈灼,第一行代表第二直接醫(yī)療,單位格代表當(dāng)前第一第二依賴下傳遞性依賴的依賴范圍也榄,比如A依賴B的范圍是provided巡莹,B依賴C的范圍是compile,則A對于C是傳遞性依賴手蝎,依賴范圍是provided榕莺。
依賴調(diào)解
大部分情況下我們只需要關(guān)心項(xiàng)目的直接依賴是什么,對間接引入的傳遞性依賴不關(guān)心棵介,但是某些情況下會(huì)因?yàn)閭鬟f性依賴導(dǎo)致同一個(gè)項(xiàng)目的依賴重復(fù)導(dǎo)入钉鸯,此時(shí)Maven會(huì)選擇路徑最短的依賴,即最短路徑優(yōu)先
邮辽,如果路徑相同會(huì)選擇在pom文件中最先申明的依賴唠雕,即第一聲明者優(yōu)先
贸营。比如A -> B -> C -> X(1.0)
和A -> D -> X(2.0)
,由于A -> D -> X(2.0)
路徑短岩睁,所以X(2.0)
會(huì)被解析使用钞脂。
排除依賴
傳遞性依賴會(huì)給項(xiàng)目隱式引入很多依賴,極大簡化了項(xiàng)目管理捕儒,但是也會(huì)帶來問題冰啃,比如當(dāng)項(xiàng)目有一個(gè)傳遞性依賴,這個(gè)依賴是不穩(wěn)定版本就需要排除掉這個(gè)依賴并且顯式的重新引入正式發(fā)布的穩(wěn)定版本刘莹,或者需要更換該依賴的版本為指定申明的版本阎毅,此時(shí)可以用exclusions
元素聲明排除的依賴
<!--Spark 依賴 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
<!-- <scope>provided</scope>-->
</dependency>
<!-- Hadoop 依賴 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
exclusions元素可以包含多個(gè)exclusion
,在exclusion中排除依賴只需要指定groupId
和artifactId
点弯,因?yàn)镸aven項(xiàng)目在groupId和artifactId相同的情況下只會(huì)引入一個(gè)version扇调。
依賴歸類
可以對在dependency中需要頻繁引用的版本寫在dependency外作Maven屬性
統(tǒng)一歸類管理。
<properties>
<spark.version>2.3.0.cloudera4</spark.version>
</properties>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${spark.version}</version>
<!-- <scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
上例中在Maven屬性中先定義了一個(gè)spark.version
為2.3.0.cloudera4
抢肛,在依賴中用${spark.version}
傳入狼钮。
查看依賴的相關(guān)命令
在項(xiàng)目根目錄下查看項(xiàng)目已經(jīng)解析的依賴
,包括直接依賴和傳遞依賴
mvn dependency:list
在項(xiàng)目根目錄下查看依賴樹
捡絮,依賴樹可以看到傳遞依賴是從哪個(gè)直接依賴被引入的
mvn dependency:tree
依賴分析
熬芜,用來分析哪些依賴被使用但是沒有顯式申明,哪些依賴被申明但是沒有使用锦援。
mvn dependency:analyze
[WARNING] Used undeclared dependencies found:
[WARNING] log4j:log4j:jar:1.2.17:compile
[WARNING] commons-dbcp:commons-dbcp:jar:1.4:compile
[WARNING] org.slf4j:slf4j-api:jar:1.7.5:compile
[WARNING] commons-collections:commons-collections:jar:3.2.2:compile
[WARNING] org.apache.zookeeper:zookeeper:jar:3.4.6:compile
[WARNING] Unused declared dependencies found:
[WARNING] org.mongodb.spark:mongo-spark-connector_2.11:jar:2.3.0:compile
[WARNING] org.apache.hive:hive-hbase-handler:jar:1.1.0-cdh5.6.1:compile
[WARNING] org.nlpcn:nlp-lang:jar:1.7.7:compile
[WARNING] org.apache.httpcomponents:httpcore:jar:4.2.5:compile
[WARNING] org.apache.httpcomponents:httpclient:jar:4.2.5:compile