Maven pom.xml與settings.xml詳解
pom.xml與settings.xml
pom.xml與setting.xml,可以說是Maven中最重要的兩個配置文件,決定了Maven的核心功能,雖然之前的文章零零碎碎有提到過pom.xml和settings.xml里面的內(nèi)容,但都是大略帶過,學(xué)習(xí)與研究地并不細(xì)致,本文的目的就是詳細(xì)研究下這兩個Maven重要的配置文件,從這兩個配置文件可以牽出非常多的Maven話題。
Maven坐標(biāo)
首先談一下為什么要使用Maven坐標(biāo)。
Maven世界擁有數(shù)量非常巨大的構(gòu)件,也就是平時使用的一些jar、war等文件,在Maven為這些構(gòu)件引入坐標(biāo)概念之前,我們無法使用任何一種方式來唯一標(biāo)識所有這些構(gòu)件。因此,如果需要使用Spring依賴,那么就去Spring官網(wǎng)尋找;如果需要使用log4j依賴,那么又去Apache官網(wǎng)尋找。又因?yàn)楦鱾€網(wǎng)站風(fēng)格迥異,大量時間花費(fèi)在了搜索和瀏覽網(wǎng)頁的工作上。沒有統(tǒng)一規(guī)范與法則,工作就無法自動化,重復(fù)性的勞動本來就應(yīng)該交給機(jī)器來做。
Maven定義了這樣一組規(guī)則:世界上任何一個構(gòu)件都可以使用Maven坐標(biāo)唯一標(biāo)識,Maven坐標(biāo)元素包括groupId、artifactId、version、packaging、classifier,現(xiàn)在只要我們提供正確的元素坐標(biāo),Maven就能找到對應(yīng)的構(gòu)件。至于去哪里下載,Maven本身內(nèi)置了一個中央倉庫的地址"http://repo1.maven.org/maven2",該中央倉庫包含了世界上絕大部分流行的開源項(xiàng)目構(gòu)件,Mavne會在需要的時候去那里下載,當(dāng)然也可以配置自己的中央倉庫地址,去自己的中央倉庫下載構(gòu)件。
舉個例子,Spring的context:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.6.RELEASE</version> </dependency
看一下下屬的各個元素:
- groupId:定義當(dāng)前Maven項(xiàng)目隸屬的實(shí)際項(xiàng)目。由于Maven項(xiàng)目和實(shí)際項(xiàng)目未必是一對一的關(guān)系,比如SpringFramework這個實(shí)際項(xiàng)目可能對應(yīng)的Maven項(xiàng)目有很多,像core、context、expression等等,因此groupId不應(yīng)該對應(yīng)項(xiàng)目隸屬的公司或組織,否則artifact將很難定義
- artifactId:定義實(shí)際項(xiàng)目中的一個Maven模塊,推薦的做法是使用實(shí)際項(xiàng)目名稱作為artifactId的前綴,這樣會很方便去尋找實(shí)際構(gòu)件
- version:定義Maven項(xiàng)目當(dāng)前所處的版本,如上面的spring-context就是4.2.6的,RELEASE表示正式發(fā)行版本
- packing:定義Maven項(xiàng)目的打包方式,這項(xiàng)不是必須的,沒列出來,不定義默認(rèn)就是jar的打包方式
- classifier:幫助定義構(gòu)件輸出的一些附屬構(gòu)件,比如xxx-javadoc.jar、xxx-sources.jar,附屬構(gòu)件與主構(gòu)件對應(yīng),這項(xiàng)是不能直接定義的
Maven坐標(biāo)的概念大致上就是這樣,理解Maven坐標(biāo),是理解Maven很重要的一步。
傳遞性依賴
什么是傳遞性依賴,以Spring舉一個例子。使用Spring的時候會依賴于其他開源的類庫,此時有兩種做法:
1、下載一個很大的.zip包,里面包含了所有Spring的jar,但是這么做往往就引入了許多不必要的依賴
2、只下載spring相關(guān)的.zip包,不包含依賴,實(shí)際使用的時候根據(jù)出錯信息,加入需要的其他依賴
顯然這兩種做法都非常麻煩,Maven的傳遞性依賴機(jī)制很好地解決了這一問題。打開spring-core-4.1.0.RELEASE的pom.xml,我截取一段關(guān)鍵部分:
<dependencies> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> <scope>compile</scope> <optional>true</optional> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> <scope>compile</scope> </dependency> ... </dependencies>
比如A項(xiàng)目依賴了spring-core,spring-core又依賴了commons-codec和commons-logging,那么commons-codec和commons-logging就是A項(xiàng)目的一個傳遞性依賴。有了傳遞性依賴機(jī)制,在使用spring-core的時候就不用去考慮它依賴了什么,也不用擔(dān)心引入多余的依賴,Maven會解析各個直接依賴的POM,將那些必要的間接依賴,以傳遞性依賴的形式引入到當(dāng)前的項(xiàng)目中去。
有了傳遞性依賴機(jī)制,一方面大大簡化和方便了依賴聲明,另一方面在大部分情況下我們只需要關(guān)心項(xiàng)目的直接依賴是什么而不用考慮這些直接依賴會引入什么傳遞性依賴,不過有時候傳遞性依賴也會有一些問題,此時我們就需要清除地知道該傳遞性依賴是從哪條路徑引入的,這就叫依賴調(diào)解,依賴調(diào)解主要有兩點(diǎn)原則:
1、A->B->C->X(1.0),A->D->X(2.0),此時兩條依賴路徑上有兩個版本的X,此時遵循路徑最近者優(yōu)先,因此X(2.0)將被解析使用
2、A->B->Y(1.0),A->C->Y(2.0),Y(1.0)和Y(2.0)的依賴長度是一樣的,從Maven2.0.9開始,此時遵循第一聲明者優(yōu)先,即順序最靠前的那個依賴優(yōu)先
排除依賴
傳遞性依賴會給項(xiàng)目隱式地引入很多依賴,這極大地簡化了項(xiàng)目依賴的管理,但是有時候這種特性也會帶來問題。比如有種情況:
當(dāng)前項(xiàng)目依賴A,A由于某些原因依賴了另外一個類庫的SNAPSHOT版本,那么這個SNAPSHOT就會成為當(dāng)前項(xiàng)目的傳遞性依賴,二SNAPSHOT的不穩(wěn)定性將直接影響到當(dāng)前的項(xiàng)目,此時就需要排除該SNAPSHOT,并且在當(dāng)前項(xiàng)目中聲明該類庫的某個正式發(fā)布的版本
排除依賴很簡單,看一下寫法:
<dependency>
<groupId>com.alibaba.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>3.2.7</version>
<exclusions>
<exclusion>
<groupId>apache-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
</exclusions>
</dependency>
這里我引入了rocketmq的依賴,但是我不想依賴rocketmq里面的apache-lang,而想要自己引入依賴,所以我就把a(bǔ)pache-lang給排除了。
這里需要注意的是,聲明exclusion的時候只需要groupId和artifactId即可,而不需要version元素,這是因?yàn)橹恍枰猤roupId和artifactId就能唯一定位依賴圖中的某個依賴。換句話說,Maven解析后的依賴中,不可能出現(xiàn)groupId和artifactId相同,但是version不同的兩個依賴。
settings.xml
settings.xml里面是Maven的基本配置,元素比較多,逐一看一下
1、proxy
proxy表示Maven的代理,看一下寫法:
<proxies> <proxy> <id>optional</id> <active>true</active> <protocol>http</protocol> <username>proxyuser</username> <password>proxypass</password> <host>proxy.host.net</host> <port>80</port> <nonProxyHosts>local.net|some.host.com</nonProxyHosts> </proxy> </proxies>
需要proxy是因?yàn)楹芏鄷r候你所在的公司基于安全因素考慮,要求你使用通過安全認(rèn)證的代理訪問因特網(wǎng)。這種情況下,就需要為Maven配置HTTP代理,才能讓它正常訪問外部倉庫,以下載所需要的資源。proxies下可以配置多個proxy元素,如果聲明了多個proxy元素,則默認(rèn)情況下第一個被激活的proxy會生效。active為true表示激活該代理,protocol表示使用的代理協(xié)議,當(dāng)然最重要的是指定正確的主機(jī)名(host)和端口(port),如果代理服務(wù)器需要認(rèn)證則配置username和password,nonProxyHost元素表示指定哪些主機(jī)名不需要代理,可以用"|"分隔多個主機(jī)名,也支持通配符"*"。
2、repository
repository表示Maven的中央倉庫,因?yàn)楸M管默認(rèn)的遠(yuǎn)程倉庫中的構(gòu)件非常龐大,但是總歸會有不滿足我們需求的時候,這時候就要用到別的中央倉庫了??匆幌聦懛ǎ?/p>
<repository>
<id>public</id>
<name>local private nexus</name>
<url>http://192.168.1.6:8081/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
可以聲明多個repository。id必須是唯一的,尤其注意,Maven自帶的中央倉庫使用的id為central,如果其他倉庫聲明也用該id,就會覆蓋中央倉庫的配置。releases和snapshots比較重要,前者表示開啟倉庫的發(fā)布版本下載支持,后者表示關(guān)閉倉庫的快照版本下載支持,這樣一來,Maven就會去倉庫下載發(fā)布版本的構(gòu)件而不會下載快照版本的構(gòu)件了。
3、server
大部分遠(yuǎn)程倉庫無須認(rèn)證就可以訪問,但是有時候處于安全方面的因素考慮,需要提供認(rèn)證信息才能訪問一些遠(yuǎn)程倉庫,處于安全考慮,認(rèn)證信息一般只放在settings.xml中,server就是認(rèn)證元素??匆幌屡渲茫?/p>
<server> <id>nexus-releases</id> <username>deployment</username> <password>deployment</password> </server>
這里的關(guān)鍵是id,這個id必須與需要認(rèn)證的repositiry元素的id完全一致才行,換句話說,正式這個id將認(rèn)證信息和倉庫配置聯(lián)系在了一起。
4、mirror
如果倉庫X可以提供倉庫Y存儲的所有內(nèi)容,那么就可以認(rèn)為倉庫X是倉庫Y的一個鏡像(mirror),換句話說,任何一個可以從Y中獲取到的構(gòu)件夠可以從X中獲取到。舉個例子,"http://maven.net.cn/content/groups/public/"是中央倉庫"http://repo1.maven.org/maven2/"在中國的鏡像,由于地理位置的因素,該鏡像往往能夠提供比中央倉庫更快的服務(wù),這就是為什么要使用mirror的原因。
看一下mirror的配置:
<mirror> <id>nexus</id> <name>internal nexus repository</name> <url>http://192.168.1.6:8081/nexus/content/groups/public</url> <mirrorOf>*</mirrorOf> </mirror>
該例子中,mirrof為*,表示該配置為所有中央倉庫的鏡像,任何對于中央倉庫的請求都會轉(zhuǎn)至該鏡像。另外三個元素id、name、url與一般倉庫配置無異,表示該鏡像倉庫的唯一標(biāo)識符、名稱以及地址。類似的,如果該鏡像需要認(rèn)證,也可以基于該id配置倉庫認(rèn)證。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
SpringBoot項(xiàng)目找不到接口報(bào)404錯誤的解決辦法
寫了一個簡單的springboot項(xiàng)目,在啟動的時候idea未報(bào)錯,瀏覽器訪問接口時報(bào)404的錯誤,所以本文給大家介紹了SpringBoot項(xiàng)目找不到接口報(bào)404錯誤的解決辦法,文中有相關(guān)的圖文供大家參考,需要的朋友可以參考下2024-12-12
Java實(shí)現(xiàn)LeetCode(報(bào)數(shù))
這篇文章主要介紹了Java實(shí)現(xiàn)LeetCode(報(bào)數(shù)),本文通過使用java實(shí)現(xiàn)leetcode的報(bào)數(shù)題目和實(shí)現(xiàn)思路分析,需要的朋友可以參考下2021-06-06
關(guān)于Mybatis-Plus?Update更新策略問題
這篇文章主要介紹了關(guān)于Mybatis-Plus?Update更新策略問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
feign name指定服務(wù)調(diào)用無效問題及解決
文章主要介紹了FeignClient注解的常用屬性,并通過一個具體的例子說明了為什么某個Feign調(diào)用需要使用url指定路徑才能訪問,最后,文章給出了解決辦法,即使用path屬性指定前綴2024-11-11
cmd中javac和java使用及注意事項(xiàng)詳解
這篇文章主要介紹了cmd中javac和java使用及注意事項(xiàng)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-07-07
SpringBoot2.x 集成 Thymeleaf的詳細(xì)教程
本文主要對SpringBoot2.x集成Thymeleaf及其常用語法進(jìn)行簡單總結(jié),其中SpringBoot使用的2.4.5版本。對SpringBoot2.x 集成 Thymeleaf知識感興趣的朋友跟隨小編一起看看吧2021-07-07

