1. 程式人生 > 其它 >(轉)Maven使用總結

(轉)Maven使用總結

Maven使用總結

依賴範圍

  • maven建立的工程的目錄中包含maintest資料夾,分別表示主程式的資料夾和測試程式的資料夾

  • maven使用scop設定依賴範圍,常用的依賴範圍如下:

    1. compile :編譯依賴範圍,在測試和執行都有效,這個是預設的依賴範圍

      • 對主程式是否有效:有效
      • 對測試程式是否 有效: 有效
      • 是否參與打包:參與``
      • 是否參與部署:參與
    2. test:測試依賴的範圍

      • 對主程式是否有效:無效
      • 對測試程式是否 有效: 有效
      • 是否參與打包:不參與
      • 典型的例子: junit
    3. provided

      • 對主程式是否有效: 有效
      • 對測試程式是否有效:有效
      • 是否參與打包:不參與
      • 是否參與部署:不參與
      • 典型的例子:servlet-api
        • 主要解決在開發中需要用到的,但是在部署的時候不需要的依賴,比如servlet-api,在開發中沒有Tomcat執行環境,因此需要這個servlet-api,但是一旦部署在Tomcat中,Tomcat中會提供這個servlet-api,如果此時在新增的話會產生依賴衝突
    4. Runtime :測試和執行時需要。編譯不需要。如JDBC驅動包

      • 對測試程式是否有效:有效
      • 對主程式是否有效:有效
      • 是否參與部署: 參與
      • 是否參與打包:參與
    5. system:系統依賴範圍。本地依賴,不在maven中央倉庫

      • 這個必須和systemPath
        結合使用,用來指定本地依賴的位置
      <!-- 新增服務提供者的jar介面 -->
             <dependency>
                 <groupId>cn.tedu.dubbo</groupId>
                 <artifactId>dubbo-provider</artifactId>
                 <version>0.0.1</version>
                 <scope>system</scope>
                 <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/dubbo-provider-helloService-0.0.1.jar</systemPath>
             </dependency>
      

依賴傳遞

  • 在開發專案的時候,我們通常需要建立多個專案,如果一個專案中需要用到另外一個專案的類或者資料,那麼需要引入這個專案快照
  • 如果HelloFriend專案依賴Hello這個專案,此時的HelloFriendpom.xml檔案如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.tedu</groupId>
    <artifactId>HelloFriend</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <dependencies>
        <!-- 新增Hello這個專案的依賴快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
</project>
  • 此時專案HelloFriend中存在依賴只有Hello專案這個jar,但是如果我們在Hello專案的pom.xml檔案中新增一個junit的依賴,這個依賴範圍為設定為compile,如下:
<dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
  </dependencies>
  • 做了上面的操作,我們可以檢視專案HelloFriendHello中都自動的匯入了Junit依賴,這個就是依賴傳遞。

注意

  • 依賴傳遞只有是依賴範圍為compile的情況下才有作用,如果我們需要一個servlet-api的依賴,因為servlet-api這個jar在部署的時候會和Tomcat衝突,因此只能設定為provided,但是此時就不能依賴傳遞了,只能在每個專案中的pom.xml檔案中都添加了

依賴排除

  • HelloFriend專案依賴Hello專案,其中compile範圍的依賴都會匯入HelloFriend
  • 使用dubbo預設會新增給我們新增spring-framework的版本為2.5.6,預設新增的依賴只能排除,不能在專案中再新增一個其他的版本,只有排除之後才能新增,否則會導致jar包衝突
  • Hello專案中的依賴為:
    <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <!-- 新增dubbo依賴的jar,會自動新增spring 2.5版本的依賴 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
        </dependency>
  • 此時HelloFriend的專案需要使用4.3.13版本的spring,那麼我們有如下解決辦法:

    1. Hello專案中改變依賴,排除spring2.5版本的:
      • 一般在公司中專案的版本都是定製好的,我們不可能隨意改動父專案中定義好的版本,因此這個方法明顯是不行的
          <!-- 使用spring4.3.13 -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>4.3.13.RELEASE</version>
          </dependency>
    
          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>dubbo</artifactId>
              <version>2.5.3</version>
                <!--排除spring2.5版本-->
                <exclusions>
                  <exclusion>
                      <groupId>org.springframework</groupId>
                      <artifactId>spring</artifactId>
                  </exclusion>
              </exclusions>
          </dependency>
    
  1. 我們可以在專案HelloFriend排除這個spring的依賴,那麼我們就可以不需要改變Hello專案中的依賴了,如下:
    • 這個才是正確的排除依賴的方式
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>
        
        <!-- 新增Hello這個專案的依賴快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <!--排除專案中的spring2.5的依賴,這個不會影響Hello專案中的版本-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>       

依賴原則

依賴路徑最短優先原則

  • 假設專案MakeFriend依賴HelloFriend,並且HelloFriend依賴Hello專案。此時Hello專案中使用的log4j 1.2.14版本的,但是在HelloFriend版本中使用的是log4j1.2.17版本的,那麼此時的MakeFriend應該選擇什麼版本呢?
  • image
  • Hello的依賴如下:
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>   
  • HelloFriend依賴如下:
    <!-- 新增Hello這個專案的依賴快照 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <!--新增1.2.17版本的log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
  • MakeFriend的依賴如下:
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>HelloFriend</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
  • 我們根據圖形可以看到MakeFriendHelloFriendlog4j1.2.17的路徑是2,但是到Hello中的log4j1.2.14的路徑為3,因此Maven會選擇HelloFriend中的log4j1.2.17版本作為MakeFriend的依賴

pom檔案中申明順序優先

  • 路徑都是一樣的情況下,那麼就要看在pom.xml檔案中申明的順序了,先申明的就使用哪個專案中的依賴版本

  • 假設現在的依賴改變了,MakeFriend現在是直接依賴HelloHelloFriend,如下圖

  • image
  • 我們可以看出此時到兩個版本的依賴都是一樣的路徑為2,那麼我們應該選擇哪個版本呢,此時就需要看看在MakeFriend中的pom.xml檔案的申明順序

    • 可以看出先申明的是HelloFriend,因此MakeFriend使用的是log4j1.2.17
<!-- 先申明HelloFriend,那麼就要使用log4j.1.2.17版本 -->
        <dependency>    
            <groupId>cn.tedu</groupId>
            <artifactId>HelloFriend</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>Hello</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

覆寫優先

生命週期

  • maven的生命週期有三個部分組成,分別為clean生命週期site生命週期default生命週期

生命週期呼叫的特點

  • 三大生命週期中也會包含各個階段,並且各個階段是有序進行的,maven為了實現構建的自動化,如果我們使用了命令呼叫生命週期後面的處理階段,那麼會從最前面的階段開始執行,不用每一個階段都執行一遍。

clean生命週期

  • 在進行真正的構建之前進行一些清理工作

  • clean生命週期包括:

    • per-clean:執行了一些需要在clean之前完成的工作
    • clean:移除所有上一次構建生成的檔案
    • post-clean:執行一些需要在clean之後立刻完成的工作
  • 當我們執行mvn:clean命令的時候只會執行per-cleanclean這兩個階段的任務,不會執行post-clean的工作

default生命週期

  • 構建的核心部分,編譯、測試、打包、部署
  • 包括如下的23個生命週期階段:
生命週期階段描述
validate 檢查工程配置是否正確,完成構建過程的所有必要資訊是否能夠獲取到。
initialize 初始化構建狀態,例如設定屬性。
generate-sources 生成編譯階段需要包含的任何原始碼檔案。
process-sources 處理原始碼,例如,過濾任何值(filter any value)。
generate-resources 生成工程包中需要包含的資原始檔。
process-resources 拷貝和處理資原始檔到目的目錄中,為打包階段做準備。
compile 編譯工程原始碼。
process-classes 處理編譯生成的檔案,例如 Java Class 位元組碼的加強和優化。
generate-test-sources 生成編譯階段需要包含的任何測試原始碼。
process-test-sources 處理測試原始碼,例如,過濾任何值(filter any values)。
test-compile 編譯測試原始碼到測試目的目錄。
process-test-classes 處理測試程式碼檔案編譯後生成的檔案。
test 使用適當的單元測試框架(例如JUnit)執行測試。
prepare-package 在真正打包之前,為準備打包執行任何必要的操作。
package 獲取編譯後的程式碼,並按照可釋出的格式進行打包,例如 JAR、WAR 或者 EAR 檔案。
pre-integration-test 在整合測試執行之前,執行所需的操作。例如,設定所需的環境變數。
integration-test 處理和部署必須的工程包到整合測試能夠執行的環境中。
post-integration-test 在整合測試被執行後執行必要的操作。例如,清理環境。
verify 執行檢查操作來驗證工程包是有效的,並滿足質量要求。
install 安裝工程包到本地倉庫中,該倉庫可以作為本地其他工程的依賴。
deploy 拷貝最終的工程包到遠端倉庫中,以共享給其他開發人員和工程。
  • 當一個階段通過 Maven 命令呼叫時,例如mvn compile,只有該階段之前以及包括該階段在內的所有階段會被執行。
  • [圖片上傳失敗...(image-7b5809-1538922827484)]

Site生命週期

  • Maven Site 外掛一般用來建立新的報告文件、部署站點等。
  • 包含以下階段
    • pre-site:執行一些需要在生成站點文件之前完成的工作
    • site:生成專案的站點文件
    • post-site:執行一些需要生成站點文件之後完成的工作
    • site-deploy:將生成站點文件部署到特定的伺服器上

Maven統一管理依賴的版本號

  • 假設如下的依賴:
    <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>

        <!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.13.RELEASE</version>
        </dependency>   
  • 那麼當我們需要改變spring的依賴版本號為4.3.12.RELEASE,那麼我們只有逐個改變version中的值,現在是兩個依賴比較好改變的,如果要有很多個的話,那麼難免會改錯,因此我們需要使用一種方式統一管理依賴的版本號。我們可以使用<properties>標籤來管理,新的配置檔案如下:
    • properties中的標籤體可以任意指定,如果需要引用定義的標籤體中的內容,那麼直接使用${標籤體}即可
    • 此時我們要是改變版本,那麼只需要改變<properties>中的版本即可
<!-- 使用properties管理版本號 -->
    <properties>
        <!-- 這裡的標籤體可以任意指定,後續只要使用${}引用標籤體即可使用其中定義的內容 -->
        <spring-version>4.3.13.RELEASE</spring-version>
    </properties>
    
    <dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <!-- version使用${} -->
            <version>${spring-version}</version>
        </dependency>

        <!-- Spring-JDBC,要和spring-webmvc的版本一致 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        
    </dependencies>

繼承

  • 我們知道只有compile範圍內的依賴才可以傳遞,但是對於testprovided中的依賴卻是不可以傳遞的,那麼必須在每個專案中都要新增依賴,此時肯定會出現每個專案中依賴版本不一致的情況,這樣對於每個人的開發來說是比較困難的,因為不同版本的依賴使用的方式也不同,此時我們就需要統一管理這個版本了。
  • 下面我們以junit的版本控制為例

步驟

  • 建立一個父工程Hello-Parent,打包的方式為pom
  • Hello-Parent中的pom.xml檔案中使用dependencyManagement管理版本,控制junit的版本依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.tedu</groupId>
  <artifactId>Hello-Parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
    
  <!-- 使用properties控制版本號 -->
  <properties>
    <junit-version>4.12</junit-version>
  </properties>
  
  <!-- 使用dependencyManagement管理版本 -->
  <dependencyManagement>
    
    <dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit-version}</version>
            <scope>test</scope>
        </dependency>
        
    </dependencies>
  </dependencyManagement>
  
</project>
  • 在子工程中使用parent標籤指定宣告對父工程的引用
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相對位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
  • 將子工程座標和父工程座標重複的地方刪除,不刪除也沒關係
  • 在子工程中刪除junitversion標籤,表明是繼承自父工程的版本,不需要指定
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <!--此時不需要指定version了,因為父工程中已經指定了-->
        </dependency>
  • 子工程全部的配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 這裡的groupId和父工程中的重複了,因此可以刪除 
    <groupId>cn.tedu</groupId>-->
    <artifactId>Hello</artifactId>
    <!-- 這裡的version版本也和父工程的重複了,因此可以刪除
    <version>0.0.1-SNAPSHOT</version> -->
    
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相對位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
    
    <dependencies>
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <!--不需要指定version-->
        </dependency>
    </dependencies>
</project>

聚合

  • 我們在開發專案的時候都是分模組開發的,此時如果想要使用maven安裝這個專案的話,那麼需要一個一個的安裝,但是我們可以使用聚合的方式,可以實現一次性安裝。並且安裝還是有先後順序的,一定要先安裝父工程,否則將會找不到依賴資訊,我們使用聚合的方式就沒有先後安裝的障礙了,maven會為我們自動的解決

步驟

  1. 建立一個maven工程,打包方式為pom,當然也是可以直接使用父工程
  2. 在pom.xml配置檔案中配置module
  3. 詳細的pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.tedu</groupId>
  <artifactId>Hello-Manager</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  
  <!-- 繼承父工程 -->
  <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>Hello-Parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <!-- 使用relativePath指定父工程的相對位置 -->
        <relativePath>../Hello-Parent</relativePath>
    </parent>
  
  <!-- 使用聚合的方式 -->
  <modules>
    <module>../Hello-Parent</module>
    <module>../Hello</module>
    <module>../HelloFriend</module>
    <module>../MakeFriend</module>
  </modules>
  
</project>

原文:https://www.jianshu.com/p/b7d08690d242

Keep moving forwards~