《Maven實戰》閱讀總結(一)Maven介紹、安裝配置、入門以及座標和依賴

(一)Maven介紹

maven:是一個跨平臺的項目管理工具,主要服務於Java平臺的項目構建、依賴管理和項目信息管理
項目構建:經過插件幫你完成項目的清理、編譯、測試、打包、部署。
依賴管理:經過座標從maven倉庫導入java類庫(jar文件)
項目信息管理:項目描述、開發者列表、版本控制系統地址、許可證、缺陷管理系統地址等。html

(二)Maven的安裝和配置

下載頁面:http://maven.apache.org/downl...
下載解壓便可。在安裝 Maven 以前,需確保安裝JDK,可經過 java -version 命令查看
環境變量配置:
1) M2_HOME = maven的bin目錄所在路徑(不包含/bin)
2) Path 添加 %M2_HOME%/bin
maven升級:下載新版本Maven解壓,修改M2_HOME路徑便可
Linux 可經過符號連接簡化 Maven升級java

Maven目錄分析

目錄 說明
bin mvn運行腳本,配置java命令, mvn / mvnDebug
boot 只包含一個plexus-classworlds jar包,Maven類加載器框架
conf settings.xml全局maven配置文件,【推薦】複製該文件至 ~/.m2/目錄下(~表示用戶目錄)
lib Maven運行須要的Java類庫,Maven jar包以及第三方依賴jar包

mvn help:system
該命令會打印出全部的Java系統屬性和環境變量spring

~/.m2目錄分析

~(用戶目錄) Winodw:C:Users用戶名 或者 C:Document and Settings用戶名
Linux: cd 回車

在用戶目錄下能夠發現.m2文件夾。
默認狀況下,.m2文件下只放置了Maven本地倉庫repository,不過大多數Maven用戶須要複製 settings.xml 到此目錄下做爲用戶配置文件。sql

Maven插件

IDE使用Maven須要安裝Maven插件,如Eclipse的m2eclipse插件,NetBeans的Maven插件數據庫

Maven安裝最佳實踐

設置環境變量MAVEN_OPTS 一般設置MAVEN_OPTS的值爲-Xms128m -Xmx512m,由於mvn命令實際執行java命令,項目較大時,使用Maven生成項目站點須要佔用大量內存,若是沒有該配置,容易獲得java.lang.OutOfMemeryException
配置用戶settings.xml 用戶可選擇配置conf中的全局配置或.m2目錄下的用戶配置,推薦使用用戶配置,避免影響系統中其餘用戶,而且配置用戶配置便於maven升級,由於Maven升級後,conf下的全局配置須要從新設置,而.m2下的用戶配置不變。
不使用IDE內嵌Maven IDE集成的Maven,一般版本比較新,不穩定,其次要確保IDE中配置Maven與命令行Maven保持一致,避免版本不一樣形成構建行爲的不一致。

(三)Maven入門

編寫POM(Project Object Model)

clipboard.png

XML頭 指定xml文檔版本和編碼方式
project 聲明POM相關的命名空間和xsd元素
modelVersion 指定當前POM模型的版本
groupId 定義了項目屬於哪一個組(Maven項目隸屬的實際項目),相似包名,域名反寫+實際項目名,如:org.sonatype.nexus
artifactId 定義了項目在組中惟一的ID,可理解爲項目名(實際項目中的一個maven項目(模塊))推薦格式:實際項目名-模塊名 如:nexus-indexer
version 指定了項目當前的版本
name 聲明瞭一個對用戶更爲友好的項目名稱,非必須,推薦聲明,方便信息交流。

編寫主代碼

默認狀況下Maven項目目錄apache

|-src
  |-main
    |-java                   Java代碼
      |-groupId.artifactId    定義包名爲項目組.項目名,全部java類都在該包下建立
    |-resources              資源目錄
  |-test                     測試目錄
    |-java                   測試Java代碼
      |-groupId.artifactId

項目編譯命令 mvn clean compile
此命令主要執行了三個插件以及插件目標api

clean:clean 刪除target目錄,默認狀況下,Maven構建的全部輸出都在target/目錄中
resource:resources 主項目資源處理
compile:compile 將項目主代碼編譯至target/classes目錄

編寫測試代碼

添加POM依賴,導入Junit jar包安全

<dependencies>    <!-- 可包含多個dependency聲明項目的依賴 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.7</version>
        <scope>test</scope>    <!-- 聲明依賴範圍,只對測試有效,在主代碼中使用junit 會編譯錯誤 -->
    </dependency>
</dependencies>

一個典型測試單元需具有三步驟:1 準備測試類及數據 2 執行要測試的方法 3 檢查結果
在測試包中建立測試類(類名不要爲Test),
編寫測試方法(void無返回值 @Test註釋),框架

項目測試命令:mvn clean test
此命令主要執行了五個插件以及插件目標eclipse

clean:clean 項目清理
resource:resources 項目主資源處理
compile:compile 主代碼編譯
resource:testResource 測試資源處理
compile:testCompile 測試代碼編譯

聲明項目編譯JDK版本

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compile-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

打包和運行

mvn clean package
該命令會在編譯、測試後執行 jar:jar
jar:jar任務負責打包,jar插件的jar項目在tartget目錄將主代碼打包成jar包,根據artifact-version.jar(項目名-版本號.jar)命名,也可經過<build>標籤中的<finalName>子標籤來自定義

mvn clean install 其餘Maven項目依賴此項目時,需將jar包安裝到Maven本地倉庫中
該命令會在編譯、測試、打包後執行install:install
install:install任務將jar包安裝到本地倉庫repository下,規則爲groupIdartifactIdversionartifactId-version.jar

可執行jar包須要設置 META-INF/MANIFEST.MF 文件中編輯 Main-Class 一行。
也可經過配置maven-shade-plugin 或 maven-jar-plugin 等插件實現

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <classesDirectory>target/classes/</classesDirectory>
        <archive>
            <manifest>
                <!-- 主函數的入口 -->
                <mainClass>cn.roylion.snake.Snake</mainClass>
                <!-- 打包時 MANIFEST.MF文件不記錄的時間戳版本 -->
                <useUniqueVersions>false</useUniqueVersions>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
            </manifest>
            <manifestEntries>
                <Class-Path>.</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Archetype項目骨架

在項目的根目錄中放置pom.xml,在src/main/java中放置項目的主代碼,在src/test/java中放置項目的測試代碼。
咱們稱這些基本的目錄結構和pom.xml文件內容爲項目骨架,Archetype能夠幫助咱們快速勾勒出項目骨架。

運行插件maven-archetype-plugin生成項目骨架:
格式:mvn groupId:artifactId:version:goal
mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate
簡化格式:mvn archetype:generate (maven2中是不安全,會自動下載最新的版本,可能獲得不穩定的SNAPSHOT版本)

執行插件以後會列出不少可用的Archetype列表,每個Archetype前面都會對應有一個編號,同時命令行會提示一個默認的編號,其對應的Archetype爲maven-archetype-quickstart,
直接回車以選擇該Archetype,或輸入指定編號回車
緊接着會Maven會提示輸入要建立項目的groupId、artifactId、version以及包名package,確認後便可生成一個maven項目。

(四)座標和依賴

maven座標

Maven定義了一組規則,世界上任何一個構件均可以使用Maven座標惟一標識,
Maven座標的元素包括 groupId、artifactId、version、packaging、classifier
中央倉庫:Maven經過座標從中央倉庫尋找相應的構件供咱們使用。

groupId 定義當前Maven項目隸屬的實際項目。由於Maven的模塊概念,Maven項目和實際項目不必定是一對一關係,一個實際項目每每會被劃分紅不少模塊。若是groupId只定義到組織級別,artifactId只能定義Maven項目(模塊),則實際項目這一層將難以定義,最後,groupId的表現形式相似包名,域名反寫+實際項目名,如:org.sonatype.nexus
artifactId 定義實際項目中的一個Maven項目(模塊),推薦使用實際項目名做爲artifactId的前綴,如nexus-indexer
version 定義Maven項目當前所處的版本。Maven定義了一套完整的版本規範,以及快照(SNAPSHOT)概念。
packaging 定義Maven項目的打包方式,未定義時,默認爲jar
classifier 幫助定義構建輸出的一些附屬構件。經過使用插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-resource.jar這樣一些附屬構件,其中包含java文檔和源代碼,此時,javadoc和resource就是這兩個附屬構件的classifier。這樣,附屬構件就擁有本身惟一的座標,

上述5個元素中,groupId、artifactId、version是必須定義的,packaging是可選的(默認爲jar),而classifier是不能直接定義的。
項目構件的文件名規則:artifactId-version[-classifier].packaging
maven倉庫的佈局也是基於maven座標的

maven依賴管理配置

<project>
...
    <dependencies>
        <dependency>
            <groupId>...</groupId>
            <artifactId>...</artifactId>
            <version>...</version>
            <type>...</type>
            <scope>...</scope>
            <optional>...<optional>
            <exclustion>
                ...
            </exclustion>
        </dependency>
        ...
    </dependencies>
...
</project>

根元素project下的dependencies能夠包含多個dependency元素,以聲明一個或多個項目依賴

groupId、artifactId、version 依賴的基本座標,Maven根據座標才能找到須要的依賴
type 依賴的類型,對應於項目座標定義的packaing,默認爲jar
scope 依賴的範圍
optional 標記依賴是否可選
exclusions 排除傳遞性依賴

依賴範圍

首先,Maven在編譯項目主代碼時須要使用一套classpath(編譯classpath);
其次,Maven在編譯和執行測試的時候會使用另一套classpath(測試classpath);
最後,實際運行Maven項目的時候,又會使用另一套classpath(運行classpath)。
依賴範圍:maven須要使用三套classpath,控制依賴與三種classpath(編譯classpath、測試classpath、運行classpath)的關係,Maven有如下幾種依賴範圍。

類型 有效範圍 說明
compile 編譯、測試、運行 編譯依賴範圍,若是沒有指定,默認使用該範圍,如 spring-core
test 測試 測試依賴範圍,如 junit
provided 編譯、測試 已提供依賴範圍,如 servlet-api
runtime 測試、運行 運行時依賴範圍,如JDBC驅動實現
system 編譯、測試 系統依賴範圍,依賴關係與provided一致,可是,使用system範圍依賴,必須經過systemPath元素顯式指定依賴文件的路徑。因爲此類依賴不經過Maven倉庫,可能會形成構建的不可移植,需謹慎使用,systemPath可引用環境變量。
<dependency>
  <groupId>javax.sql</groupId>
   <artifactId>jdbc-stdext</artifactId>
   <version>2.0</version>
   <scope></scope>
   <systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
import 導入依賴範圍,該依賴範圍不會對三種classpath產生實際的影響。

傳遞性依賴

假設:A->B->C
當項目A依賴於B包,而B包又依賴於C包,故須要引入C包。
使用Maven只須要引入B包便可,C包由Maven經過傳遞性依賴引入。
Maven經過傳遞性依賴機制,解析各個直接依賴的POM,將那些必要的間接依賴,以傳遞性依賴的形式引入到當前的項目中。

傳遞性依賴與依賴範圍

假設:A->B->C
A依賴B -> 第一直接依賴 依賴範圍
B依賴C -> 第二直接依賴 依賴範圍
A依賴C -> 傳遞性依賴 依賴範圍 由第一直接依賴和第二直接依賴決定,以下圖
clipboard.png
總結:
第二直接依賴範圍是compile,傳遞性依賴範圍與第一直接依賴範圍一致;
第二直接依賴範圍是test,依賴不得以傳遞;
第二直接依賴範圍是provided,只第一直接依賴範圍也爲provided時,傳遞性範圍一樣爲provided;
第二直接依賴範圍是runtime,除第一直接依賴範圍爲compile時爲runtime,傳遞性依賴範圍與第一直接依賴範圍一致。

依賴調解

假設:A->B->C-X(1.0)    A->D->X(2.0)
傳遞性依賴機制引入不通版本的X時,發生依賴重複,Maven遵循的第一原則:路徑最近者優先。
該例中X(1.0)路徑長度爲3,X(2.0)路徑長度爲2。所以X(2.0)會被解析使用
當路徑長度相同時,Maven(2.0.9以後)定義第二原則:第一聲明者優先。

可選依賴(optional 標記依賴是否可選)

假設:A->B , B->X(可選) , B->Y(可選)
若是全部這個三個依賴的範圍都是compile,那麼X,Y就是A的compile範圍傳遞性依賴,可是,因爲X,Y是可選依賴,依賴將不得以傳遞。

可選依賴的使用場景:項目B具備兩個特性,特性一依賴於X,特性二依賴於Y,而且這兩個特性是互斥的,用戶沒法同時使用。
好比B是一個持久層隔離工具包,它支持多個數據庫,包括MySql(假設驅動依賴X)、Oracle(假設驅動依賴Y),
在構建項目B時,須要引入這兩種數據庫的驅動程序,但在引入項目B時,只會依賴一種數據庫,
此時項目B構建時需聲明依賴X,Y可選(<scope>true</scope>),
當項目A依賴項目B時,X,Y項目依賴不會被傳遞,同時項目A根據實際需求,顯式聲明X或Y依賴(如項目使用MySql數據庫時,項目A依賴項目B,同時顯式聲明X依賴)

說明:在理想狀態下,是不該該使用可選依賴。可選依賴是基於一個項目實現多個特性,違背了面向對象設計中的單一職責性原則。

排除依賴

假設:A->B-X(1.0)
傳遞性依賴會隱式地引入不少依賴,如依賴X(1.0),這極大地簡化項目依賴管理,但這種特性也會帶來一些問題。
例如,我須要依賴X(2.0)時,可使用排除依賴排除X(1.0),同時顯式聲明X(2.0)依賴。
代碼中使用exclusions元素聲明排除依賴,exclusions能夠包含一個或多個exclusion子元素,所以能夠排除一個或多個傳遞性依賴。
注意:聲明exclusion時只須要groupId和artifactId,不須要version。由於Maven解析後的依賴中,不會存在groupId和artifactId相同,而version不一樣的兩個依賴(依賴調解特性)。

歸類依賴

引入同一項目的不一樣模塊時,這些依賴的版本都是相同的,如Spring Framework
這裏簡單用到了Maven屬性,首先使用properties元素聲明Maven屬性(定義版本),並在dependency聲明中引用這個版本(${})。

<project>
    ...
    <properties>
        <springframework.version>2.5.6</springframework.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        ...
    </dependencies>
    ...
</project>

優化依賴

瞭解Maven項目的依賴,去除多餘的依賴,顯式地聲明某些必要的依賴

Maven會自動解析全部項目的直接依賴和傳遞性依賴,而且根據規則正確判斷每一個依賴的範圍,對於一些依賴衝突,也能進行調節,以確保一個構件只有惟一的版本在依賴中存在。在這些工做以後,最後獲得的那些依賴被稱爲已解析依賴。
mvn dependency:list 查看已解析依賴列表及其依賴範圍

在此基礎上,還能進一步瞭解已解析依賴的信息,將直接在當前項目POM聲明的依賴定義爲頂層依賴,而這些頂層依賴的依賴則定義爲第二層依賴,以此類推,有第3、第四層依賴。當這些依賴經解析後,就會構成一個依賴樹。經過這個依賴樹就能清楚得看到某個依賴是經過哪條傳遞路徑引入的。
mvn dependency:tree 查看當前項目的依賴樹

mvn dependency:analyze 幫助分析當前項目的依賴
經過分析依賴樹,能夠獲得兩個重要結果:
1 Used undeclared dependencies:意指項目中使用到的,可是沒有顯式聲明的依賴。(存在隱患)
假設:A->B->C
若是項目A->C時,而且項目A並無顯示聲明C依賴時,而使用B的傳遞依賴C時,當升級直接依賴B,傳遞依賴C也可能發送變化,而且這種變化不易發現,致使當前項目出錯。如接口改變,致使編譯失敗。所以,顯式聲明任何項目中直接用到的依賴。
2 Unused declared dependencies:意指項目中未使用的,但顯式聲明的依賴。
對於這一類依賴,不要簡單的直接刪除其聲明,而是應該仔細分析,由於dependency:analyze工具只會分析編譯主代碼和測試代碼須要用到的依賴,一些執行測試和容許時須要的依賴它就發現不了。

相關文章
相關標籤/搜索