午夜三区_久久久久亚洲一区二区三区_夜夜操操操_久久久精彩视频_日韩在线观看视频一区二区_91视频观看

mvn 不是內部命令 也不是可運行的程序(每個程序員都該學會的Maven知識)

抖帥宮 353 2023-09-12

mvn 不是內部命令 也不是可運行的程序(每個程序員都該學會的Maven知識)-第1張-觀點-玄機派

來源頭條作者:Java架構人生

以前的日子

以前我們寫代碼時,jar包都默認放在一個叫 /lib 的目錄下,然后把該目錄設置為classpath可以讀取到的目錄,如下圖所示:

某一天我們新加了一個功能,需要用到一個比較古老的 z.jar 包,這時我們到網上去各種搜索,由于比較罕見,最終在某個 xxx軟件園 中找到了他。然后我們把 z.jar 包拷貝到 /lib 目錄下:

這時運行后報了一堆的錯,原因是 z.jar 包有很多的依賴項,分別是 z1.jar , z2.jar , z3.jar。這時的你是否有種想要罵人的沖動?但是沖動歸沖動,代碼還是要寫,jar包還是要找,自己挖的坑,哭著也要填完啊。

歷經千難萬險,終于在1個博客中找到了 z1.jar , z2.jar , z3.jar 的下載鏈接,但是需要支付積分才能下載。。為了得到這些jar包,我們又注冊了一個賬號,發了幾個評論,賺到足夠的積分后,終于把那三個jar包下載下來了。然后趕緊把他們拷貝到 /lib 下去:

湊夠了jar包之后,再次運行項目,終于能成功運行了,真是謝天謝地!

過了半個月,老板說我們 項目A 非常不錯,現在我們準備再啟動一個 項目B 作為他的兄弟項目。這時你開始搭建 項目B 的框架了,把所有需要用到的jar包從 項目A 拷貝到 項目B 中:

從此你又開始了打怪升級的日子了。

現在的日子

隨著科技的發展,改革開放的浪潮席卷了大地,也席卷了IT界,一大堆生產力工具被創造出來了,俗話說的好,工欲善其事必先利其器。有了好的生產力工具,要做的事必定是事半功倍!而 Maven 就是一種為了解放我們程序猿的生產力工具。

程序猿在日常工作中需要用到大量的jar包,有的是框架包如:netty,sentinel等,有的是工具包如:hutool,有的是公司內部的私有包如:xx-framework等等。

一個項目中可能充斥著各種各樣的jar包,如果我們用手工的方式去一個一個的管理的話,那樣就會迷失在jar包的海洋里,這時我們通過 Maven 這種管理jar包的工具來幫助我們解決這個繁瑣又棘手的問題,可以讓我們專心于自己的功能與業務。

其實 Maven 是一套軟件工程管理和整合工具。他有很多的功能包括但不限于以下幾點:

工程的創建、構建、測試依賴的管理倉庫的管理自動化部署。。。

我們日常中用的最多的可能就是工程與依賴的管理了,其他的用到的頻率不多。

有了 Maven 之后,我們:

不需要為每個項目都創建一個 /lib 目錄用來存放各種jar包了不需要為到哪去尋找我需要的jar包而發愁了不需要為引用的jar包去尋找他所依賴的jar包了。。。

結構

下面是一個典型的maven項目的結構圖:

倉庫

在 Maven 的術語中,倉庫是一個位置(place),例如目錄,可以存儲所有的工程 jar 文件、library jar 文 件、插件或任何其他的工程指定的文件。

嚴格意義上說,Maven 只有兩種類型的倉庫:

本地(local)遠程(remote)

本地倉庫

Maven 的本地倉庫是機器上的一個文件夾。它在你第一次運行任何 maven 命令的時候創建。

Maven 的本地倉庫保存你的工程的所有依賴(library jar、plugin jar 等)。當你運行一次 Maven 構建時,Maven 會自動下載所有依賴的 jar 文件到本地倉庫中。它避免了每次構建時都引用存放在遠程倉庫上的依賴文件。

Maven 的本地倉庫默認被創建在 ${user.home}/.m2/repository 目錄下。要修改默認位置,只要在 settings.xml 文件中定義另一個路徑即可,例如:

/anotherDirectory/.m2/respository

遠程倉庫

Maven 的遠程倉庫可以是任何其他類型的存儲庫,可通過各種協議,例如 file://和 http:// 來訪問。

這些存儲庫可以是由第三方提供的可供下載的遠程倉庫,例如Maven 的中央倉庫(central repository):

repo.maven.apache.org/maven2

uk.maven.org/maven2

也可以是在公司內的FTP服務器或HTTP服務器上設置的內部存儲庫,用于在開發團隊和發布之間共享私有的 artifacts。

中央倉庫

Maven 的中央倉庫是 Maven 社區維護的,里面包含了大量常用的庫,我們可以直接引用,但是前提是我們的項目能夠訪問外網。

私有倉庫

除了 Maven 的中央倉庫外,還有一種就是私有倉庫,這種倉庫通常都是企業內部創建的一個私有庫,用于一些內部jar包的維護與共享。由于網絡原因和鑒于安全性的考慮,很多公司的內外網是隔離的,要想直接訪問中央倉庫是不可能的,并且直接把內部資源暴露在互聯網上也是非常危險的,所以這時就需要創建一個私有庫。

那這些倉庫之間的關系是怎樣的呢?或者說一個 Maven 項目想要獲取一個jar包的話,他該從哪個倉庫中去獲取呢?下圖就是一個簡單的描述:

首先 Maven 會到本地倉庫中去尋找所需要的jar吧,如果找不到就會到配置的私有倉庫中去找,如果私有倉庫中也找不到的話,就會到配置的中央倉庫中去找,如果還是找不到就會報錯。但是這中間只要在某一個倉庫中找到了就會返回了,除非倉庫中有更新的版本,或者是snapshot版本。

那么 Maven 的遠程倉庫是怎么配置的呢?假設我們要配置一個中央倉庫,可以像下面這樣配置:

最佳實踐

但是官方并不推薦直接配置遠程倉庫,例如直接配置一個中央倉庫,而是通過 倉庫管理器 來下載我們所需要的jar包。試想一下如果你所在的公司有幾千甚至上萬的開發者,每個人都單獨配置一個中央倉庫,那每個人都到中央倉庫中去下載所需的jar,這就退化成最原始的模式,并且是一個巨大的資源浪費。

那什么是 倉庫管理器 呢?倉庫管理器是一種專用服務器應用程序,目的是用來管理二進制組件的存儲庫。對于任何使用 Maven 的項目,倉庫管理器的使用被認為是必不可少的最佳實踐。

倉庫管理器提供了以下基本用途:

充當中央Maven存儲庫的專用代理服務器提供存儲庫作為Maven項目輸出的部署目標

使用倉庫管理器可以獲得以下優點和功能:

顯著減少了遠程存儲庫的下載次數,節省了時間和帶寬,從而提高了構建性能由于減少了對外部存儲庫的依賴,提高了構建穩定性與遠程SNAPSHOT存儲庫交互的性能提高提供了一個有效的平臺,用于在組織內外交換二進制工件,而無需從源代碼中構建工件。。。

已知的開源和商業存儲庫管理器有以下這些:

Apache Archiva(開源)CloudRepo(商業)Cloudsmith套餐(商業)JFrog Artifactory開源(開源)JFrog Artifactory Pro(商業)Sonatype Nexus OSS(開源)Sonatype Nexus Pro(商業)packagecloud.io(商業)

鏡像

Mirror 則相當于一個代理,它會攔截去指定的遠程 Repository 下載構件的請求,然后從自己這里找出構件回送給客戶端。配置 Mirror 的目的一般是出于網速考慮。

Repository 和 Mirror 是兩個不同的概念:前者本身是一個倉庫,可以堆外提供服務,而后者本身并不是一個倉庫,它只是遠程倉庫的網絡加速器。

需要注意的是很多本地倉庫搭建工具往往也提供 Mirror 服務,比如Nexus就可以讓同一個URL,既用作 internalrepository,又使它成為所有 repository 的 Mirror。

如果 倉庫X 可以提供 倉庫Y 存儲的所有內容,那么就可以認為 X是Y的一個鏡像。這也意味著,任何一個可以從某個倉庫中獲得的構件,都可以從它的鏡像中獲取。

舉個例子:http://maven.net.cn/content/groups/public/ 是中央倉庫 http://repo1.maven.org/maven2/ 在中國的鏡像,由于地理位置的因素,該鏡像往往能夠提供比中央倉庫更快的服務。

因此,可以在Maven中配置該鏡像來替代中央倉庫。在settings.xml中配置如下代碼:

\的值為central,表示該鏡像是中央倉庫的鏡像,任何對于中央倉庫的請求都會轉至該鏡像,如下圖所示:

對于鏡像的最佳實踐是結合私服。由于私服可以代理任何外部的公共倉庫(包括中央倉庫),因此,對于組織內部的Maven用戶來說,使用一個私服地址就等于使用了所有需要的外部倉庫,這可以將配置集中到私服,從而簡化Maven本身的配置。在這種情況下,任何需要的構件都可以從私服獲得,私服就是所有倉庫的鏡像。

例如可以這樣來配置一個代理所有倉庫的鏡像:

\的值為星號,表示該鏡像是所有Maven倉庫的鏡像,任何對于遠程倉庫的請求都會被轉至:internal-repository-url 這個地址。

下面給出一張 Maven 官方的架構圖:

生命周期

生命周期是由 一組 有 順序 的 階段 構成的一個整體,這么說可能有點繞,那讓我們來關注他里面的幾個重要的點:

一組:指的是可能有多個順序:指的是按照順序執行,執行某一個階段的指令時會依次先執行該階段之前的指令階段:指的是具體要執行的內容

例如 Maven 有三個內置的構建生命周期: default, clean 和 site。每個生命周期都由一系列的階段所構成,比如 default 生命周期的一個簡易階段如下,完整的生命周期請參考官方文檔:

上圖中的每一個節點都是一個 階段 ,階段的執行是按順序的,一個階段執行完成之后才會執行下一個階段。比如我們執行了一個如下的指令:

mvn install

他實際會執行 install 階段之前的所有階段,然后才會執行 install 階段本身。

PS:當我們的項目是多模塊的,我們在最頂層執行該指令時,Maven 會遍歷每一個子模塊,依次執行所有的階段。

坐標

說到 Maven 的坐標,我們首先就需要想到 GAV ,即 groupId artifactId version。由這三個屬性就可以唯一確定一個jar包了。其中每個屬性的意義如下:

groupId:表示一個團體,可以是公司、組織等artifactId:表示團體下的某個項目version:表示某個項目的版本號

他們之間的關系是一對多的,即每個團體下可以有多個項目,每個項目可以有多個版本號,可以用下面這張圖來表示:

依賴

Maven 核心特點之一是依賴管理。一旦我們開始處理多模塊工程(包含數百個子模塊或者子工程)的時候,模塊 間的依賴關系就變得非常復雜,管理也變得很困難。針對此種情形,Maven 提供了一種高度控制的方法。

依賴傳遞

依賴傳遞很好理解,假設 B 依賴于 C,當 A 需要依賴 B 時,則 A 自動獲得了對 C 的依賴。依賴傳遞有時非常好,當我們需要依賴很多jar包時,我們可以聲明一個包來依賴所有的jar,然后只要依賴這個包就可以了。但是有時又很麻煩,因為很可能會造成依賴的沖突。

依賴沖突

當同一個項目中由于不同的jar包依賴了相同的jar包,此時就會發生依賴沖突的情況,如下圖所示:

當項目中依賴了a和c,而a和c都依賴了b,這時就造成了沖突。為了避免沖突的產生,Maven 使用了兩種策略來解決沖突,分別是 短路優先 和 聲明優先 。

短路優先

短路優先的意識是,從項目一直到最終依賴的jar的距離,哪個距離短就依賴哪個,距離長的將被忽略掉。例如下圖所示:

聲明優先

聲明優先的意思是,通過jar包聲明的順序來決定使用哪個,最先聲明的jar包總是被選中,后聲明的jar包則會被忽略,如下圖所示:

依賴排除

如果我們只想引用我們直接依賴的jar包,而不想把間接依賴的jar包也引入的話,那可以使用依賴排除的方式,將間接引用的jar包排除掉,如下面的配置所示:

解決沖突

項目中出現沖突,大體都是因為上面所描述的原因,然后 Maven 在選擇jar包時,選擇了一個錯的包,導致出現問題,這時我們就需要人為來干預他,告訴 Maven 使用哪個正取的包。下面讓我舉個例子來說明沖突產生后該如何解決。

我們原本運行得好好的一個項目,突然有一次啟動的時候,報錯了,如下圖所示:

可以看到有報了一個 NoSuchMethodError ,看到這個錯,多半都是因為沖突導致的。

錯誤說的是找不到 javax.servlet.ServletContext 類中的 getVirtualServerName 方法了,那我們在 idea 中搜索一下 javax.servlet.ServletContext 類,看看是否存在多個的情況,如下圖所示:

可以發現確實在兩個jar包中都找到了 javax.servlet.ServletContext 這個類,那我們打開他們看看哪個類沒有我們需要方法:

可以很清楚的看到,在 servlet-api-3.0.jar 包中沒有找到我們需要的方法,而 Maven 肯定是選擇了這個包。那就讓我們來看下依賴樹吧,看看 Maven 是怎樣選擇了錯誤的包的。

在項目目錄中輸入如下指令:

mvn dependency:tree -Dverbose -Dincludes=javax.servlet:servlet-api

Maven 將打印出 servlet-api-3.0.jar 的包的依賴樹,如下圖所示:

然后在輸入如下指令:

mvn dependency:tree -Dverbose -Dincludes=javax.servlet:servlet-api

Maven 將打印出 tomcat-embed-core-8.5.31.jar 的包的依賴樹,如下圖所示:

我們分析下原因,從 Maven 中打印出的依賴樹來看,發現很奇怪的事:

servlet-api-3.0.jar 包是在 xx-service 模塊中引入的,從 xx-web 到他的深度為6,

tomcat-embed-core-8.5.31.jar 包是在 xx-web 模塊中引入的,從 xx-web 到他的深度為3。

那按照短路優先的規則,Maven 應該會選擇 tomcat-embed-core-8.5.31.jar 包才對,現在沒有選擇他,那原因肯定只有一個了:聲明優先!

說明 servlet-api-3.0.jar 包比 tomcat-embed-core-8.5.31.jar 包先聲明。

我們發現 servlet-api-3.0.jar 包是在 xx-service 中被引入的,

而 tomcat-embed-core-8.5.31.jar 是在 spring-boot-starter-web 中被引入的。

那只要能證明在 xx-web 中 xx-service 先于 spring-boot-starter-web 聲明就可以了,讓我們去 xx-web 中看看:

事實證明了我們的猜想是正確的, xx-service 確實比 spring-boot-starter-web 先聲明!

可以用圖形表示成如下:

那知道原因了,要解決這個沖突,就很好辦了,有兩種方法:

在 xx-web 中將 xx-service 放到 spring-boot-starter-web 后面聲明在 xx-service 中找到引入 servlet-api-3.0.jar 包將他排除掉

依賴管理

聚合

將多個項目同時運行就稱為聚合,如下就是一個多模塊的項目:

聚合的優勢在于可以在一個地方編譯多個 pom 文件。

PS:聚合時 packaging 必須要是 pom

繼承

跟java類的繼承類似,Maven 的繼承特性也會繼承父pom中的依賴,假設我們定義了一個父pom:

然后在子pom中引入這個父pom:

使用dependencyManagement,可對依賴進行管理。子類只要不引用這個里面寫的groupId + artifactId,則不會添加依賴,這樣防止造成重復加了包:如果不使用dependencyManagement,那么只要寫了dependency,子pom中會全部添加到依賴中,而其中很多包可能都用不上。

插件

插件是 Maven 的核心,所有執行的操作都是基于插件來完成的。

為了讓一個插件中可以實現眾多的相類似的功能,Maven 為插件設定了目標,一個插件中有可能有多個目標。其實生命周期中的每個階段都是由插件的一個具體目標來執行的

例如可以用下面的方式配置一個插件:

配置目標 goal 的目的是:這樣在執行 mvnpackage 的時候,就會自動執行 mvn source:jar-no-fork了,jar-no-fork這個目標是用來進行源碼打包的。

除了可以在build元素中配置插件,當然也可以在parent項目中,用pluginManagement來配置,然后在子項目繼承即可使用。

PS:通過插件我們可以做很多事,比如通過mybatis-generator 我們可以生成很多DAO層的代碼,再配合通用Mapper+lombok使用的話就可以使你的代碼非常簡潔,絕對的生產力工具!

指令

下面列舉一些常用的 maven 指令:

指令參數

上面列舉的只是比較通用的命令,其實很多命令都可以攜帶參數以執行更精準的任務。 Maven命令可攜帶的參數類型如下:

-D 傳入屬性參數

比如命令: mvnpackage-Dmaven.test.skip=true以 -D開頭,將 maven.test.skip 的值設為 true ,就是告訴maven打包的時候跳過單元測試。

同理, mvn deploy-Dmaven.test.skip=true 代表部署項目并跳過單元測試。

-P 使用指定的Profile配置

比如項目開發需要有多個環境,一般為開發,測試,預發,正式4個環境,在pom.xml中的配置如下:

profiles定義了各個環境的變量 id, filters中定義了變量配置文件的地址,其中地址中的環境變量就是上面 profile中定義的值, resources中是定義哪些目錄下的文件會被配置文件中定義的變量替換。

通過maven可以實現按不同環境進行打包部署,命令為:

mvn package -P dev

其中 dev 為環境的變量id,代表使用Id為 dev 的 profile。

-e 顯示maven運行出錯的信息

-o 離線執行命令,即不去遠程倉庫更新包

-X 顯示maven允許的debug信息

-U 強制去遠程更新snapshot的插件或依賴,默認每天只更新一次

舉個例子

將自己的jar包部署到遠程倉庫去,可以使用 deploy 指令:

最后說下我們為什么要學習maven,大概可以收獲這些好處吧:

提高自己的生產力更好的管理項目中的jar包自己開發的jar包可以共享給別人遇到jar包沖突問題可以不求人。。。

原文地址:https://dwz.cn/ddPIxQUZ

作者:逅弈

上一篇:兌乾卦解卦(乾卦和兌卦的生克關系)
下一篇:infj是最差勁的人格,你屬于最稀有的
相關文章

 發表評論

暫時沒有評論,來搶沙發吧~

返回頂部小火箭
主站蜘蛛池模板: 亚洲精品乱码久久久久久按摩观 | 成人a在线 | 欧美国产激情二区三区 | 精品免费在线 | 久久精品久久精品久久精品 | 日韩精品免费看 | 欧美日韩亚洲国产 | 97人人超碰 | 毛片视频免费观看 | 青青久视频 | 亚洲精品视频久久 | 成人福利在线观看 | 自拍偷拍在线视频 | 亚洲精品视频在线 | 国产成人精品免高潮在线观看 | 国产综合久久 | 精品二区 | 国产成人精品一区二区三区四区 | 国产美女在线精品免费 | 久久久久国产精品午夜一区 | 在线成人| 91在线免费视频 | 在线视频h | 亚洲v日韩v综合v精品v | 欧美日韩在线精品 | 户外露出一区二区三区 | 超碰日本| 中文字幕日韩欧美 | 日本三级全黄三级三级三级口周 | 亚洲人成人一区二区在线观看 | 国产高清视频一区 | 国产一二区视频 | 亚洲第一区国产精品 | 久久精品亚洲精品国产欧美kt∨ | 天堂视频免费 | 男女一区二区三区 | 久久成人精品一区二区三区 | 99久久精品国产一区二区三区 | 欧美日韩综合视频 | 欧美视频在线播放 | 精品日韩一区 |