NO IMAGE
文件版本開發工具測試平臺工程名字日期作者備註
V1.02016.07.08lutianfeinone

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>
  • 聚合與繼承的關係
  • 聚合主要為了快速構建專案
  • 繼承主要為了消除重複