文檔版本 | 開發工具 | 測試平臺 | 工程名字 | 日期 | 作者 | 備註 |
---|---|---|---|---|---|---|
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>
- 聚合與繼承的關係
- 聚合主要爲了快速構建項目
- 繼承主要爲了消除重複