日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Maven知识点整理

發(fā)布時間:2025/3/15 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Maven知识点整理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Maven不僅是依賴管理工具,準(zhǔn)確來說是一個項目管理工具,貫穿了整個項目生命周期,編譯,測試,打包,發(fā)布... 依賴是使用Maven坐標(biāo)來定位的,而Maven坐標(biāo) 主要 由GAV(groupId, artifactId, version)構(gòu)成。 Maven思想:約定大于配置。

依賴歸類

使用<properties>來歸類管理。 示例: <dependencies><dependency><groupId>org.spring.framework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.spring.framework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.spring.framework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.spring.framework</groupId><artifactId>spring-mock</artifactId><version>${spring.version}</version></dependency> </dependencies><properties><spring.version>2.5</spring.version> </properties>

?多模塊 & 繼承

在Maven的多模塊工程中,都存在一個pom類型的工程作為根模塊,該工程只包含一個pom.xml文件,在該文件中以模塊(module)的形式聲明它所包含的子模塊,即多模塊工程。

在子模塊的pom.xml文件中,又以parent的形式聲明其所屬的父模塊,即繼承。

多模塊的好處是你只需在根模塊中執(zhí)行Maven命令,Maven會分別在各個子模塊中執(zhí)行該命令,執(zhí)行順序通過Maven的Reactor機(jī)制決定。

1)如果保留webapp和core中對maven-multi-module的父關(guān)系聲明,即保留 “<parent>... ?</parent>”,而刪除maven-multi-module中的子模塊聲明,即“<modules>...<modules>”,會發(fā)生什么情況?此時,整個工程已經(jīng)不是一個多模塊工程,而只是具有父子關(guān)系的多個工程集合。如果我們在maven-multi-module目錄下執(zhí)行“mvn clean install”,Maven只會在maven-multi-module本身上執(zhí)行該命令,繼而只會將maven-multi-module安裝到本地Repository中,而不會在webapp和core模塊上執(zhí)行該命令,因為Maven根本就不知道這兩個子模塊的存在。另外,如果我們在webapp目錄下執(zhí)行相同的命令,由于由子到父的關(guān)系還存在,Maven會在本地的Repository中找到maven-multi-module的pom.xml文件和對core的依賴(當(dāng)然前提是他們存在于本地的Repository中),然后順利執(zhí)行該命令。

(2)如果保留maven-multi-module中的子模塊聲明,而刪除webapp和core中對maven-multi-module的父關(guān)系聲明,又會出現(xiàn)什么情況呢?此時整個工程只是一個多模塊工程,而沒有父子關(guān)系。Maven會正確處理模塊之間的依賴關(guān)系,即在webapp模塊上執(zhí)行Maven命令之前,會先在core模塊上執(zhí)行該命令,但是由于core和webapp模塊不再繼承自maven-multi-module,對于每一個依賴,他們都需要自己聲明,比如我們需要分別在webapp和core的pom.xml文件中聲明對Junit依賴。

依賴范圍(scope)

引入依賴范圍的原因示例:

1 例如Junit,將Junit的jar包打包到發(fā)布包是沒有必要的。

2 例如servlet-api,為了編譯通過,我們引入servlet-api jar包;但因為web容器也會提供servlet-api,如果將servlet-api打包至WAR包,就會造成依賴沖突。

示例:

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.4</version> <scope>test</test> </dependency><dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.1</version> <scope>provided</scope> </dependency>

?scope詳解:

1 complie

默認(rèn)值。參與當(dāng)前項目的編譯,后續(xù)的測試,運行,是一個比較強的依賴。

2 test

參與包括測試代碼的編譯,執(zhí)行。比較典型的如junit。

3 runtime

被依賴項目無需參與項目的編譯,不過后期的測試和運行周期需要其參與。
與compile相比,跳過編譯而已.
oracle jdbc驅(qū)動架包就是一個很好的例子,一般scope為runntime。另外runntime的依賴通常和optional搭配使用,optional為true。我可以用A實現(xiàn),也可以用B實現(xiàn)。

4 provided

打包的時候不包進(jìn)去,別的設(shè)施(如Web Container)會提供。
事實上該依賴?yán)碚撋峡梢詤⑴c編譯,測試,運行等周期。
相當(dāng)于compile,但是在打包階段做了exclude的動作。

5 system

從參與度來說,也provided相同,不過被依賴項不會從maven倉庫抓,而是從本地文件系統(tǒng)拿,一定需要配合systemPath屬性使用。

?

依賴范圍及作用
依賴范圍(scope)主源碼classpath可用測試源碼classpath可用會被打包
compile 缺省值TRUETRUETRUE
testFALSETRUEFALSE
runtimeFALSETRUETRUE
providedTRUE(外界提供)TRUEFALSE

scope的依賴傳遞

A–>B–>C。當(dāng)前項目為A,A依賴于B,B依賴于C。知道B在A項目中的scope,那么怎么知道C在A中的scope呢?答案是:
當(dāng)C是test或者provided時,C直接被丟棄,A不依賴C;
否則A依賴C,C的scope繼承于B的scope。

下面是一張nexus畫的圖。?

分類器(classifer)

GAV是Maven坐標(biāo)最基本最重要的組成部分,但GAV不是全部。

還有一個元素叫做分類器(classifier),90%的情況你不會用到它,但有些時候,分類器非常不可或缺。
舉個簡單的例子,當(dāng)我們需要依賴TestNG的時候,簡單的聲明GAV會出錯,因為TestNG強制需要你提供分類器,以區(qū)別jdk14和jdk15,我們需要這樣聲明對TestNG的依賴:

<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>5.7</version><classifier>jdk15</classifier> </dependency>

你會注意到maven下載了一個名為testng-5.7-jdk15.jar的文件。

其命名模式實際上是<artifactId>-<version>-<classifier>.<packaging>。

理解了這個模式以后,你就會發(fā)現(xiàn)很多文件其實都是默認(rèn)構(gòu)件的分類器擴(kuò)展,如 myapp-1.0-test.jar, myapp-1.0-sources.jar。

分類器還有一個非常有用的用途是:我們可以用它來聲明對test構(gòu)件的依賴,比如,我們在一個核心模塊的src/test/java中聲明了一些基礎(chǔ)類,然后我們發(fā)現(xiàn)這些測試基礎(chǔ)類對于很多其它模塊的測試類都有用。沒有分類器,我們是沒有辦法去依賴src/test/java中的內(nèi)容的,因為這些內(nèi)容不會被打包到主構(gòu)件中,它們單獨的被打包成一個模式為<artifactId>-<version>-test.jar的文件。

我們可以使用分類器來依賴這樣的test構(gòu)件:理解了分類器,那么可供依賴的資源就變得更加豐富。

<dependency><groupId>org.myorg.myapp</groupId><artifactId>core</artifactId><version>${project.version}</version><classifier>test</classifier> </dependency>

?依賴管理(dependencyManagement)

實際的項目中,你會有一大把的Maven模塊,而且你往往發(fā)現(xiàn)這些模塊有很多依賴是完全項目的,A模塊有個對spring的依賴,B模塊也有,它們的依賴配置一模一樣,同樣的groupId, artifactId, version,或者還有exclusions, classifer。

細(xì)心的分會發(fā)現(xiàn)這是一種重復(fù),重復(fù)就意味著潛在的問題,Maven提供的dependencyManagement就是用來消除這種重復(fù)的。

正確的做法是:

1. 在父模塊中使用dependencyManagement配置依賴

2. 在子模塊中使用dependencies添加依賴

dependencyManagement實際上不會真正引入任何依賴,dependencies才會。但是,當(dāng)父模塊中配置了某個依賴之后,子模塊只需使用簡單groupId和artifactId就能自動繼承相應(yīng)的父模塊依賴配置。

依賴配置越復(fù)雜,依賴管理所起到的作用就越大,它不僅能夠幫助你簡化配置,它還能夠幫你鞏固依賴配置,也就是說,在整個項目中,對于某個構(gòu)件(如mysql)的依賴配置只有一種,這樣就能避免引入不同版本的依賴,避免依賴沖突。

示例:

父模塊:

<project><modelVersion>4.0.0</modelVersion><groupId>org.sonatype.mavenbook</groupId><artifactId>a-parent</artifactId><version>1.0.0</version>...<dependencyManagement><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.2</version></dependency>...<dependencies></dependencyManagement>

子模塊:

<project><modelVersion>4.0.0</modelVersion><parent><groupId>org.sonatype.mavenbook</groupId><artifactId>a-parent</artifactId><version>1.0.0</version></parent><artifactId>project-a</artifactId>...<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency></dependencies> </project>

傳遞依賴 & 依賴沖突

依賴沖突時,Maven采用“最近獲勝策略(nearest wins strategy)”。

如果一個項目最終依賴于相同artifact的多個版本,在依賴樹中離項目最近的那個版本將被使用。

示例:

github源代碼:https://github.com/davenkin/maven-dependency-conflict-demo

resolve-web項目的依賴關(guān)系如下:

根據(jù)Maven的transitive依賴機(jī)制,resolve-web將同時依賴于project-common的1.0和2.0版本,這就造成了依賴沖突。而根據(jù)最近獲勝策略,Maven將選擇project-common的1.0版本作為最終的依賴。

?在resolve-web中執(zhí)行"mvn dependency:tree -Dverbose"可以看到resolve-web的依賴關(guān)系:

[INFO] resolve-web:resolve-web:war:1.0-SNAPSHOT[INFO] +- junit:junit:jar:3.8.1:test[INFO] +- project-B:project-B:jar:1.0:compile[INFO] | \- project-C:project-C:jar:1.0:compile[INFO] | \- (project-common:project-commmon:jar:2.0:compile - omitted for conflict with 1.0)[INFO] +- project-A:project-A:jar:1.0:compile[INFO] | \- project-common:project-commmon:jar:1.0:compile[INFO] \- javax.servlet:servlet-api:jar:2.4:provided

由上可知,project-common:project-commmon:jar:2.0被忽略掉了。此時在resolve-web的war包中將只包含project-common的1.0版本,于是問題來了。由于project-common的1.0版本中不包含sayGoodBye()方法,而該方法正是project-C所需要的,所以運行時將出現(xiàn)“NoSuchMethodError”。

?

對于這種有依賴沖突所導(dǎo)致的問題,我們有兩種解決方法。

方法1:顯式加入對project-common 2.0版本的依賴。先前的2.0版本不是離resolve-web遠(yuǎn)了點嗎,那我們就直接將它作為resolve-web的依賴,這不就比1.0版本離resolve-web還近嗎?在resove-web的pom.xml文件中直接加上對project-common 2.0 的依賴:

<dependency> <groupId>project-common</groupId> <artifactId>project-commmon</artifactId> <version>2.0</version> </dependency>

方法2:resolve-web對project-A的dependency聲明中,將project-common排除掉。在resolve-web的pom.xml文件中修改對project-A的dependency聲明:

<dependency> <groupId>project-A</groupId> <artifactId>project-A</artifactId> <version>1.0</version> <exclusions> <exclusion> <groupId>project-common</groupId> <artifactId>project-commmon</artifactId> </exclusion> </exclusions> </dependency>

方法3:另外,我們還可以在project-A中將對project-common的依賴聲明為optional,optional即表示非transitive,此時當(dāng)在resolve-web中引用project-A時,Maven并不會將project-common作為transitive依賴自動加入,除非有別的項目(比如project-B)聲明了對project-common的transitive依賴或者我們在resolve-web中顯式聲明對project-common的依賴(方法一)。

?Profile

Maven的Profile用于在不同的環(huán)境下應(yīng)用不同的配置。一套配置即稱為一個Profile。

?Maven提供了Activation機(jī)制來激活某個Profile,它既允許自動激活(即在某些條件滿足時自動使某個Profile生效),也可以手動激活。

Profile可配置“<activeByDefault>true</activeByDefault>”,表明該Profile默認(rèn)即是生效的。

<profiles><profile><id>apple</id><activation><activeByDefault>true</activeByDefault></activation><properties><fruit>APPLE</fruit></properties></profile><profile><id>banana</id><properties><fruit>BANANA</fruit></properties></profile></profiles>

為了打印出fruit這個屬性,我們再向pom.xml中添加一個maven-antrun-plugin插件,我們可以通過該插件的echo任務(wù)來打印屬性信息。我們將該打印配置在Maven的initialize階段(任何階段都可以):

<plugin><artifactId>maven-antrun-plugin</artifactId><executions><execution><phase>initialize</phase><goals><goal>run</goal></goals><configuration><tasks><echo>Fruit:${fruit}</echo></tasks></configuration></execution></executions></plugin>

配置完成之后,執(zhí)行:“mvn initialize”,由于id為apple的Profile默認(rèn)生效,此時將在終端輸出“APPLE”字樣:

......[INFO] Executing tasks[echo] Fruit:APPLE[INFO] Executed tasks......

如果要使用id為banana的Profile,我們可以顯式地指定使用該Profile:"mvn initialize -Pbanana"

私服(Repository)

?Maven提高篇系列之(三)——使用自己的Repository(Nexus)

Plugin

Maven就其本身來說只是提供一個執(zhí)行環(huán)境,它并不知道需要在項目上完成什么操作,真正操作項目的是插件(plugin)。

比如編譯Java有Compiler插件,打包有Jar插件等。

所以要讓Maven完成各種各樣的任務(wù),我們需要配置不同的插件,甚至自己編寫插件。?

?

參考資料:

Maven提高篇系列之(一)——多模塊 vs 繼承

Maven提高篇系列之(三)——使用自己的Repository(Nexus)

Maven提高篇系列之(四)——使用Profile

Maven提高篇系列之(五)——處理依賴沖突

Maven提高篇系列之(六)——編寫自己的Plugin

?Maven依賴中的scope詳解

Maven最佳實踐:管理依賴

轉(zhuǎn)載于:https://www.cnblogs.com/ken-jl/p/8610775.html

總結(jié)

以上是生活随笔為你收集整理的Maven知识点整理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。