Maven 入門學習.md

文檔版本 開發工具 測試平臺 工程名字 日期 作者 備註
V1.0 2016.07.08 lutianfei none

MAVEN 說明

  • 翻譯爲:“專家”,“內行”
  • Maven是跨平臺的項目管理工具。主要服務於基於Java平臺的項目構建依賴管理項目信息管理

  • 理想的項目構建?

    • 高度自動化跨平臺可重用的組件
  • 什麼是依賴?爲什麼要進行依賴管理?

    • 自動下載,統一依賴管理
  • 管理哪些項目信息?

    • 項目名稱描述等,開發人員信息,開發者信息等

MAVEN 模型


爲什麼使用Maven

  • Eclipse
    • 手工操作較多,編譯、測試、部署等工作都是獨立的,很難一步完成
    • 每個人的IDE配置都不同,很容易出現本地代碼換個地方編譯就出錯
  • Ant
    • 沒有一個約定的目錄結構
    • 必須明確讓ant做什麼,什麼時候做,然後編譯,打包
    • 沒有生命週期,必須定義目標及其實現的任務序列
    • 沒有集成依賴管理
  • Maven
    • 擁有約定,知道你的代碼在哪裏,放到哪裏去
    • 擁有一個生命週期,例如執行 mvn install 就可以自動執行編譯,測試,打包等構建過程
    • 只需要定義一個pom.xml,然後把源碼放到默認的目錄,Maven幫你處理其他事情
    • 擁有依賴管理,倉庫管理

MAVEN 安裝與初始化說明

MAVEN 安裝

  • 直接解壓bin壓縮包即可。

  • 目錄說明

    • bin:含有mvn運行的腳本
    • boot:含有plexus-classworlds類加載器框架
    • conf:含有settings.xml配置文件
    • lib:含有Maven運行時所需要的java類庫
    • LICENSE.txt, NOTICE.txt, README.txt針對Maven版本,第三方軟件等簡要介紹
  • 設置MAVEN_HOME環境變量

    • 升級時只需要下載最新版本,解壓縮後重新設置MAVEN_HOME環境變量即可
  • 設置MAVEN_OPTS環境變量
    • -Xms128m -Xmx512m
  • 配置用戶範圍的settings.xml
    • MAVEN_HOME/conf/settings.xml 全局的
      • ~/.m2/settings.xml
      • 默認倉庫:當前用戶路徑C:\Users\[UserName]\.m2
  • 設置自定義jar包倉庫
    • 在上述路徑中將<localRepository>/path/to/local/repo</localRepository>中的路徑改爲自己所需的路徑D:\maven\repository
    • settings.xml文件複製到與repository同目錄下。且兩邊要求一樣。
    • localRepository:用戶倉庫,用於檢索依賴包路徑
    • 注意:用戶級別的倉庫在全局配置中一旦設置,全局配置將不再生效,轉用用戶所設置的倉庫,否則使用默認路徑倉庫

Maven約定

  • src/main/java —— 存放項目的.java文件
  • src/main/resources —— 存放項目資源文件,如spring, hibernate配置文件
  • src/test/java —— 存放所有測試.java文件,如JUnit測試類
  • src/test/resources —— 測試資源文件
  • target —— 項目輸出位置
  • pom.xml——maven項目核心配置文件


MyEclipse中的MAVEN插件使用

  • 加入maven插件

  • 設置maven倉庫

新建maven工程

測試工程1

  • One.java
public class One {
    public String say(String name){
        return "hello " +name+" one";
    }
}


  • OntTest.java
package ledouya.one;

import junit.framework.Assert;

import org.junit.Test;

public class OneTest {
    @Test
    public void testSay(){
        One one = new One();
        String ret = one.say("lutianfei");
        Assert.assertEquals("hello lutianfei one",ret);
    }
}


  • pom.xml文件說明
    • maven 的模型指的是pom文件的規範
    • 羣組ID:單位域名反寫
    • 項目ID:一個單位只有一個域名,但是一個單位可以做多個項目
    • 版本號:用於描述開發過程的階段性標識
<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>
    <!-- 羣組ID:單位域名反寫 -->
    <!-- <groupId>cn.itcast</groupId> -->
    <!-- 項目ID:一個單位只有一個域名,但是一個單位可以做多個項目 -->
    <artifactId>One</artifactId>
    <!-- 版本號:用於描述開發過程的階段性標識 -->
    <version>1.0.15-RELEASE</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <!-- 依賴管理 -->
    <dependencies>
        <!-- 具體的依賴 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>juint</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>


測試工程2

  • 第一步 : 新建maven工程與工程1一致。
  • 第二步 : 代碼編寫

  • Two.java

package ledouya.two;

import ledouya.one.One;

public class Two {
    public String say(String name){
        One one = new One();
        String ret = one.say("lutianfei");
        return ret + " two";
    }
}
  • TwoTest.java
package ledouya.two;

import org.junit.Test;

import junit.framework.Assert;

public class TwoTest {
    @Test
    public void testSay(){
        Two two = new Two();
        String ret = two.say("miaolu");
        Assert.assertEquals("hello miaolu one two", ret);
    }
}
  • 第三步 : 添加依賴(工程1中的pom文件已經包含了依賴說明)
    <dependency>
      <groupId>ledouya</groupId>
       <artifactId>one</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  • 第四步:將所依賴的工程1打包加載到倉庫中。

完成以上步驟幾個運行工程2。

Maven 座標

  • Maven座標主要組成

    • groupId:定義當前Maven項目隸屬項目
    • artifactId:定義實際項目中的一個模塊
    • version:定義當前項目的當前版本
    • packaging:定義該項目的打包方式
  • Maven爲什麼使用座標?

    • Maven世界擁有大量構建,我們需要找一個用來唯一標識一個構建的統一規範擁有了統一規範,就可以把查找工作交給機器。

依賴管理

  • 其中依賴範圍scope 用來控制依賴和編譯,測試,運行的classpath的關係. 主要的是三種依賴關係如下:
    • 1.compile: 默認編譯依賴範圍。對於編譯,測試,運行三種classpath都有效
    • 2.test:測試依賴範圍。只對於測試classpath有效
    • 3.provided:已提供依賴範圍。對於編譯,測試的classpath都有效,但對於運行無效。因爲由容器已經提供,例如servlet-api
    • 4.runtime:運行時提供。例如:jdbc驅動

依賴配置 : 傳遞性依賴和可選依賴,排除依賴

依賴管理-傳遞依賴

  • 例子:
    Two中使用One
    Three中使用Two
    稱Two是Three的直接依賴
    稱One是Three的間接依賴
    C->B B->A
    C直接依賴B
    C間接依賴A
依賴範圍對傳遞依賴的影響
![](http://i1.piimg.com/567571/710e0de3830d663f.png)

依賴管理-可選依賴

  • <optional> true/false 控制當前對象是否向下傳遞
  • 當一個項目A依賴另一個項目B時,項目A可能很少一部分功能用到了項目B,此時就可以在A中配置對B可選依賴

    • 舉例來說,一個類似hibernate的項目,它支持對mysql、oracle等各種數據庫的支持,但是在引用這個項目時,我們可能只用到其對mysql的支持,此時就可以在這個項目中配置可選依賴。
  • 配置可選依賴的原因:

    • 1、節約磁盤、內存等空間;
    • 2、避免license許可問題;
    • 3、避免類路徑問題,等等。
  • 示例:

<project>
  ...
  <dependencies>
    <!-- declare the dependency to be set as optional -->
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <optional>true</optional> <!-- value will be true or false only -->
    </dependency>
  </dependencies>
</project>
  • 假設以上配置是項目A的配置,即:Project-A --> Project-B。在編譯項目A時,是可以正常通過的。

  • 如果有一個新的項目X依賴A,即:Project-X -> Project-A。此時項目X就不會依賴項目B了。

  • 如果項目X用到了涉及項目B的功能,那麼就需要在pom.xml中重新配置對項目B的依賴。


依賴管理-排除依賴

  • 設置當前依賴中是否使用間接依賴
<exclusions>
    <exclusion>
  • 當一個項目A依賴項目B,而項目B同時依賴項目C,如果項目A中因爲各種原因不想引用項目C,在配置項目B的依賴時,可以排除對C的依賴。

  • 示例(假設配置的是A的pom.xml,依賴關係爲:A --> B; B --> C):

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
          <groupId>sample.ProjectC</groupId>
          <artifactId>Project-C</artifactId>
        </exclusion>
      </exclusions> 
    </dependency>
  </dependencies>
</project>


  • 當然,對於多重依賴,配置也很簡單,參考如下示例:

    • Project-A-> Project-B-> Project-D -> Project-E
  • A對於E相當於有多重依賴,我們在排除對E的依賴時,只需要在配置B的依賴中進行即可:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>sample.ProjectA</groupId>
  <artifactId>Project-A</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
          <artifactId>Project-E</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

依賴管理-依賴衝突

  • 如果直接與間接依賴中包含有同一個座標不同版本的資源依賴,以直接依賴的版本爲準(就近原則)
  • 如果直接依賴中包含有同一個座標不同版本的資源依賴,以配置順序下方的版本爲準(就近原則)

生命週期

  • Maven生命週期就是爲了對所有的構建過程進行抽象和統一
  • 包括項目清理,初始化,編譯,打包,測試,部署等幾乎所有構建步驟

  • Maven三大生命週期

    • clean:清理項目的
    • default:構建項目的
    • site:生成項目站點的
  • 生命週期Maven有三套相互獨立的生命週期,請注意這裏說的是“三套”,而且“相互獨立”,這三套生命週期分別是:

    • Clean Lifecycle 在進行真正的構建之前進行一些清理工作。
    • Default Lifecycle 構建的核心部分,編譯,測試,打包,部署等等。
    • Site Lifecycle 生成項目報告,站點,發佈站點。
  • 再次強調一下它們是相互獨立的,你可以僅僅調用clean來清理工作目錄,僅僅調用site來生成站點。當然你也可以直接運行 mvn clean install site 運行所有這三套生命週期。

生命週期clean

  • clean生命週期每套生命週期都由一組階段(Phase)組成,我們平時在命令行輸入的命令總會對應於一個特定的階段。比如,運行mvn clean ,這個的clean是Clean生命週期的一個階段。有Clean生命週期,也有clean階段。Clean生命週期一共包含了三個階段:
    • pre-clean 執行一些需要在clean之前完成的工作
    • clean 移除所有上一次構建生成的文件
    • post-clean 執行一些需要在clean之後立刻完成的工作
  • mvn clean 中的clean就是上面的clean,在一個生命週期中,運行某個階段的時候,它之前的所有階段都會被運行,也就是說,mvn clean 等同於 mvn pre-clean clean ,如果我們運行 mvn post-clean ,那麼 pre-clean,clean 都會被運行。這是Maven很重要的一個規則,可以大大簡化命令行的輸入。

生命週期default

  • Default生命週期Default生命週期是Maven生命週期中最重要的一個,絕大部分工作都發生在這個生命週期中。這裏,只解釋一些比較重要和常用的階段:
    • validate
    • generate-sources
    • process-sources
    • generate-resources
    • process-resources 複製並處理資源文件,至目標目錄,準備打包。
    • compile 編譯項目的源代碼。
    • process-classes
    • generate-test-sources
    • process-test-sources
    • generate-test-resources
    • process-test-resources 複製並處理資源文件,至目標測試目錄。
    • test-compile 編譯測試源代碼。
    • process-test-classes
    • test 使用合適的單元測試框架運行測試。這些測試代碼不會被打包或部署。
    • prepare-package
    • package 接受編譯好的代碼,打包成可發佈的格式,如 JAR 。
    • pre-integration-test
    • integration-test
    • post-integration-test
    • verify
    • install 將包安裝至本地倉庫,以讓其它項目依賴。
    • deploy 將最終的包複製到遠程的倉庫,以讓其它開發人員與項目共享。
  • 運行任何一個階段的時候,它前面的所有階段都會被運行,這也就是爲什麼我們運行mvn install 的時候,代碼會被編譯,測試,打包。此外,Maven的插件機制是完全依賴Maven的生命週期的,因此理解生命週期至關重要。

生命週期site:

  • Site生命週期pre-site 執行一些需要在生成站點文檔之前完成的工作
  • site 生成項目的站點文檔
  • post-site 執行一些需要在生成站點文檔之後完成的工作,並且爲部署做準備
  • site-deploy 將生成的站點文檔部署到特定的服務器上
  • 這裏經常用到的是site階段和site-deploy階段,用以生成和發佈Maven站點,這可是Maven相當強大的功能,Manager比較喜歡,文檔及統計數據自動生成,很好看。

插件

  • Maven的核心僅僅定義了抽象的生命週期,具體的任務都是交由插件完成的
  • 每個插件都能實現多個功能,每個功能就是一個插件目標
  • Maven的生命週期與插件目標相互綁定,以完成某個具體的構建任務
  • 例如compile就是插件maven-compiler-plugin的一個插件目標
<build>
    <plugins>
        <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
              <version>2.2.1</version>
              <executions>
                        <execution>
                    <goals>
                        <goal>jar-no-fork</goal>
                            </goals>
                            <phase>verify</phase>
                </execution>
                </executions>
          </plugin>
    </plugins>
</build>

繼承

  • 爲了消除重複,我們把很多相同的配置提取出來
    • 例如:grouptId,version等
    • 父工程設置爲被繼承
    • <packaging>pom</packaging>
    • 子工程繼承父工程,省略父工程中定義的座標除訪問名稱中的所有設定,添加繼承父工程
<parent>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <relativePath>../父工程項目名</relativePath>
</parent>
  • 父工程統一管理子工程依賴版本
<dependencyManagement>    
    <dependencies>
        //添加公共依賴包
    </dependencies>
</dependencyManagement>
  • 子工程僅僅添加依賴包,無需添加版本,版本由父工程繼承而來,爲了進一步便於管理,將所有的版本管理設置在一起,設置爲系統屬性值
<properties>
    <junit.version>4.9</junit.version>
    ……
</properties>
  • 引用使用${junit.version}格式進行,只能在依賴範圍設置



  • 父工程統一管理子工程依賴關係
    • 如果所有子工程都需要依賴某些包,父工程可以通過設置依賴,將依賴關係傳遞到子工程中
<dependencies>
    //添加公共依賴包
</dependencies>

聚合

  • 如果我們想一次構建多個項目模塊,那我們就需要對多個項目模塊進行聚合
<modules>
    <module>../子項目名稱1</module>
    <module>../子項目名稱2</module>
     <module>../子項目名稱3</module>
</modules>
  • 聚合與繼承的關係
  • 聚合主要爲了快速構建項目
  • 繼承主要爲了消除重複
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章