maven入門總結

原文地址: pjmike的博客java

前言

上週去實習入職,領完電腦裝maven環境的時候被gank了,覺得本身裝好了,settings.xml文件也導入了,鏡像也換成了國內阿里雲鏡像了,結果搭建maven項目時發現,POM.xml文件導不進依賴項,提示錯誤,並且使用IDEA編寫maven依賴項沒有自動提示功能。mysql

通過一番折騰,發現是首先公司使用的IDEA社區版,功能並無專業版強大,用慣了專業版着實不習慣,第二個是個人settings.xml文件裏的阿里雲鏡像寫錯了,由於是直接在網上找的,看上去都差很少,其實倒是本身踩到了坑。後來師兄給了我一個公司特定版本的setting.xml配置文件才搞好。linux

從這個小問題,我也意識到我本身對Maven的掌握仍是不夠,因此纔有這篇文章對Maven的一些知識點進行系統性的學習,並概括總結。git

"對你遇到每個知識點要有一個系統的認識",忘記在哪看到的了,感受挺受用的。github

maven倉庫的分類

Maven的倉庫分爲兩類: 本地倉庫和遠程倉庫,當maven根據座標尋找構件的時候,它首先會查看本地倉庫,若是本地倉庫存在此構件,則直接使用,若是不存在,或者須要查看是否有更新的構件版本,Maven就會去遠程倉庫查找,發現須要的構件以後,下載到本地倉庫再使用。若是本地倉庫和遠程倉庫都沒有須要的構建,就會報錯。spring

中央倉庫是Maven核心自帶的遠程倉庫,它包含了絕大部分開源的構建,在默認配置下,當本地倉庫沒有maven須要的的構件時,它就會嘗試從中央倉庫中下載。sql

私服是另外一種特殊的遠程倉庫,爲了節省帶寬和事件,應該在局域網內架設一個私有的倉庫服務器,用其代理全部外部的遠程倉庫,內部的項目還能部署到私服上供其餘項目使用。緩存

maven

本地倉庫

默認狀況下,不論是在Windows仍是linux下,每一個用戶在本身的用戶目錄下都有一個路徑名爲.m2/repository/的倉庫目錄。服務器

有時候,由於某些緣由(例如C盤空間不夠),用戶會想要自定義本地倉庫目錄地址,這時,能夠編輯文件~/.m2/settings.xml,設置localRepository想要的倉庫地址,例如:框架

<localRepository>d:maven/maven.m2/repository</localRepository>

複製代碼

默認狀況下,~/.m2/settings.xml文件是不存在的,用戶須要從maven安裝目錄下/conf/settings.xml文件再進行編輯。

一個構件只有在本地倉庫以後,才能由其餘maven項目使用。

遠程倉庫

安裝好maven以後,若是不執行任何maven命令,本地倉庫目錄是不存在的,當用戶輸入第一條maven命令以後,maven纔會建立本地倉庫,而後根據配置和須要,從遠程倉庫下載構件到本地倉庫

遠程倉庫的認證

大部分遠程倉庫都不須要認證,可是仍是有些倉庫須要認證,認證配置以下:

<server>
      <id>deploymentRepo</id>
      <username>repouser</username>
      <password>repopwd</password>
    </server>
複製代碼
  • username用戶名
  • password密碼
  • id必須與POM中須要認證的repository元素的id一致。

中央倉庫

本地原始的本地倉庫是空的,maven必須知道至少一個可用的遠程倉庫,才能在執行maven命令的時候下載到須要的構件,中央倉庫就是這樣一個默認的遠程倉庫,maven的安裝文件自帶了中央倉庫的配置。/MAVEN_HOME/lib/maven2.2x-uber.jar

私服

私服是一種特殊的遠程倉庫,它是架設到局域網內的倉庫服務,私服代理廣域網上的遠程倉庫,供局域網內的maven用戶使用。當maven須要下載構件的時候,它從私服請求,若是私服不存在該條件,則從外部的遠程倉庫下載,緩存到私服上以後。

maven私服

鏡像

若是倉庫X能夠提供倉庫Y存儲的全部內容,那麼就能夠認爲X是Y的一個鏡像,換句話說,任何一個能夠從倉庫Y得到的構件,都可以從它的鏡像中獲取。

好比說,maven.net.cn/content/gro… 是中央倉庫 repo1.maven.org/maven2/ 在中國的鏡像,因爲地理位置的因素,該鏡像每每可以提供比中央倉庫更快的服務。在國內咱們更多的是使用阿里雲提供的鏡像服務:

<mirror> 
      <id>alimaven</id>
      <name>aliyun maven</name> 
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
      <mirrorOf>central</mirrorOf>
</mirror> 
複製代碼
  • mirrorOf爲central,表示該配置爲中央倉庫的鏡像,任何對於中央倉庫的請求都會轉到該鏡像,而若是爲*,那麼匹配全部的遠程倉庫
  • id惟一標識符
  • name名稱
  • url地址

maven的快照版本

在maven的世界中,任何一個項目都有本身的版本,版本的值多是1.0.0,1.3-alpha-4,2.0,2.1-SNAPSHOT等

  • 1.0.0,1.3-alpha-4和2.0是穩定的發佈版本
  • 2.1-SNAPSHOT是不穩定的快照版本

那爲何還區分穩定版和快照版呢?好比你接到一個需求,針對公司的二方庫進行開發,新增某某接口等,可是你的需求不是很穩定,須要總是修改二方庫裏的內容,而公司某項目A又要依賴該二方庫,若是沒有快照版本,那麼二方庫每次修改好了,都會指定一個新的版本給項目A,項目A每次又要修改二方庫的版本,這樣就會顯得很是麻煩。

而Maven的快照版本機制就是爲了解決上述問題的,項目A只須要引入快照版本號,好比2.1-SNAPSHOT版本,由於是快照版本,針對二方庫的每次修改而且發佈後,在發佈過程當中,maven會自動爲構件打上時間戳,有了該時間戳,Maven就能夠隨時找到倉庫中該構件2.1-SNAPSHOT版本最新的文件,也就是說項目A能夠拉取到最新的版本內容。

默認狀況下,Maven天天檢查一次更新,固然用戶也可使用命令行-U參數強制讓maven檢查更新,如 mvn clean install -U

maven的生命週期

maven的生命週期就是爲了對全部的構建過程進行抽象和統一,這個生命週期包含了項目的清理、初始化、編譯、測試、打包、集成測試、驗證、部署和站點生成等幾乎全部構建步驟,可是maven的生命週期是抽象的,這意味着生命週期自己不作任何實際的工做,在maven的設計中,實際的任務都交給插件來完成。

maven有三個內置的構建生命週期:default、clean和site,可是平時工做中咱們更多的關注的是maven更加細分的生命週期階段:

  • validate: 驗證項目是否正確,全部必要的信息是否可用
  • complie: 編譯項目的源代碼
  • test: 用合適的單元測試框架測試編譯好的源代碼
  • package: 將編譯好的代碼使用它的指定的可分發的格式進行打包 (jar/war)
  • verify: 對集成測試的結果執行檢查,以確保知足質量標準
  • install: 將軟件包安裝到本地倉庫,可用做本地其餘項目的依賴項
  • deploy: 將軟件包發佈到遠程倉庫中

maven-lifecycle

階段的執行是按順序的,一個階段執行完成以後纔會執行下一個階段,好比執行mvn install命令,實際上它會執行install階段以前的全部階段,而後纔會執行install階段自己。

前面就提到過在maven的設計中,實際的任務(好比編譯源代碼)是交給插件來完成的,下面展現幾個經常使用的插件:

maven-plugins

maven座標和依賴

maven的一大功能就是管理項目依賴,爲了能自動化解析任何一個Java構件,maven就必須將它們惟一標識,這就依賴管理的底層基礎——座標,也就是GAV,即groupId artifactId version,由這三個屬性能夠惟一肯定一個jar包

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

如下面這個依賴項爲例

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.1.4.RELEASE</version>
    <scope>test</scope>
</dependency>
複製代碼

除了GAV,仍是一個scope配置,其實就是依賴的範圍,依賴範圍就是用來控制依賴與三種classpath(編譯 classpath、測試classpath、運行classpath)的關係,Maven主要有如下幾種依賴範圍:

  • complie
    • 編譯依賴範圍,默認值,對三種classpath都有有效
  • test
    • 測試依賴範圍,只對測試classpath有效,好比JUnit,它只在編譯測試代碼及運行測試的時候須要
  • provided
    • 對編譯和測試classpath有效,但在運行時無效
  • runtime
    • 運行時依賴範圍,對於測試和運行classpath有效,但在編譯主代碼時無效
  • system
    • 與provided依賴範圍一致

依賴衝突

談到依賴,就不得不提使用maven可能碰到的依賴衝突問題,當一個項目中不一樣的Jar包依賴了相同的jar包時,此時就會發生依賴衝突的問題,爲了不衝突的發生,maven使用如下幾種策略來解決衝突:

  • 短路優先
    • 短路優先是指,從項目一直到最終依賴的jar包的距離,哪一個距離短就依賴哪一個,距離長的被忽略
    • 好比狀況1:a.jar——>b.jar ;狀況2: d.jar——>c.jar——>b.jar,兩種狀況都依賴於b.jar,可是狀況1距離最短,選擇狀況1的方式
  • 聲明優先
    • 聲明優先的意思是,經過jar包聲明的順序來決定使用哪一個,最早聲明的jar包老是被選中,後聲明的jar包則會被忽略

那麼上面只是兩種策略,具體如何作呢?有兩種作法,手動分析衝突並解決和使用maven helper插件

  • 手動法(以commons-logging包爲例)
    • 首先分析衝突jar包的依賴路徑,使用命令: mvn dependency:tree -Dverbose -Dincludes=commons-logging:commons-loggging,該命令將打印出全部依賴了groupId和artifactId都爲commons-logging的jar包的依賴路徑。
    • 在兩個衝突的版本中,選擇一個所需的版本
    • 在pom.xml文件中將衝突的依賴排除,可以使用某衝突jar包
  • maven helper 插件
    • IDEA中安裝該插件,選擇confilcts,會列出有衝突的jar,右側在要排除的版本上右鍵點擊Exclude

maven的聚合與繼承

1. 聚合

以下所示爲聚合:

<packaging>pom</packaging> 
<modules>
    <module>module-1</module>
    <module>module-2</module>
    <module>module-3</module>
 </modules>
複製代碼
  • 聚合時packaging必須是pom

2. 繼承

父POM:

<groupId>com.pjmike</groupId>
<artifactId>maven-parent</artifactId> 
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
   <dependencies>
      <dependency>
            <groupId>mysql</groupId> 
            <artifactId>mysql-connector-java</artifactId> 
            <version>5.1.30</version>
      </dependency>
   </dependencies>
</dependencyManagement>
複製代碼

子POM,引入父POM

<!-- 指定parent,說明是從哪一個pom繼承 -->
<parent>
    <groupId>com.pjmike</groupId> 
    <artifactId>maven-parent</artifactId> 
    <version>0.0.1-SNAPSHOT</version>
    <!-- 指定相對路徑 --> 
    <relativePath>../maven-parent</relativePath>
</parent>

<!-- 只須要指明groupId + artifactId,就能夠到父pom找到了,無需指明版本 -->
<dependencies>
    <dependency>
        <groupId>mysql</groupId> 
        <artifactId>mysql-connector-java</artifactId> 
    </dependency>
</dependencies>
複製代碼

使用dependencyManagement可對依賴進行管理,子類只要不引用這個裏面寫的依賴,則不會添加,這樣防止了重複加包,若是不使用dependencyManagement,那麼只要寫了dependency,子pom中會所有添加到依賴中。

maven經常使用指令

下面列舉一些比較常見的maven命令

maven

小結

下面總結一個maven相關知識的思惟導圖,以下圖

maven

上面總結的maven知識點並非特別全,更多關於maven的講解能夠參閱《maven實戰》這本書。

參考資料 & 鳴謝

相關文章
相關標籤/搜索