一起學Maven(Maven的依賴管理特性)

前情回顧

    在上一節中介紹了通過工具eclipse構建了maven項目,並且僅僅做了簡單的運行演示,本節將通過eclipse構建出一個項目中的幾個模塊,並且通過這幾個模塊的聯繫講解maven中依賴的特性。

項目構建

    本章通過一個典型的項目構建過程來學習Maven的依賴傳遞性。

    項目獲取地址http://download.csdn.net/detail/songdeitao/6927445

    總共分爲三個模塊的項目編寫user-core,user-log,user-service,在user-core中主要實現基本的實體類,初始文件,dao的編寫,在user-log中簡單模擬日誌文件的記錄,在user-service模塊中主要引入前兩個模塊,從而進行編寫service模塊的功能,在這裏模塊的編寫不是重點,這些都會給出代碼,然而進行Maven依賴與傳遞的講解纔是重點,所以很多時候代碼都是爲了演示出效果,和實際開發還是有些差別,但所指代的思想是項目中所存在的。

普通依賴

    Maven的依賴是使用Maven座標來定位的,而Maven座標主要由GAV(groupId, artifactId, version)構成,因此,使用任何一個依賴之間,你都需要知道它的Maven座標,在之前的第二章節中,從引入了Maven的中央工廠的網頁,在此引入一個常用的Maven搜索jar包的資源庫網頁http://www.mvnrepository.com/,在此可以查找所需要的jar文件的GAV,比如在本文的第一章節的如下配置:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.10</version>
</dependency>

    可以通過如下列圖所示的步驟進行查找到,而且以後的jar包查找過程都是按照此步驟進行獲取,然後複製到pom.xml<dependencies>元素下,Maven就能在本地或者遠程倉庫中找到對應的jar包(不一定可以找到所有的jar文件)

                        圖1

                        圖2


                         圖3

    此配置聲明瞭一個對junit的依賴,它的groupId是junit, artifactId是junit, version是4.10。這一組GAV構成了一個Maven座標,基於此,Maven就能在本地或者遠程倉庫中找到對應的junit-4.10.jar文件。

傳遞依賴

一:

首先緊跟第二章節的新建項目構建出如下圖所示的結構圖,


          圖4

通過此模塊的構建,主要說明Maven的一下幾個問題

    1、目錄結構的默認構建,比如資源文件的src/main/resources目錄的構建

    2、pom.xml文件的使用到的jar包的引入,比如在user-core中的文件內容如下所示:

<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>com.steven.user</groupId>
	<artifactId>user-core</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>user-core</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.1.1.Final</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.8</version>
		</dependency>


	</dependencies>
</project>
            通過資源庫中查找到相應的jar包,放到pom.xml中之後,Eclipse就會自動會和本地資源庫或者遠程倉庫中進行匹配,如果本地中沒有,就會通過網絡下載從遠程倉庫中下載到本地倉庫中。

    3、進行Maven項目模塊的打包和加入到本地資源庫的命令,如圖所示


                    圖5

    這樣就可以執行打包或者將打包後的jar添加到本地倉庫中。

二:

接着引入user-log,user-service


           圖6                            圖7

其中user-log的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>com.steven.user</groupId>
	<artifactId>user-log</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>user-log</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.5</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.4</version>
		</dependency>
	</dependencies>
</project>
    其中user-service的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>com.steven.user</groupId>
	<artifactId>user-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>user-service</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>${project.groupId}</groupId>
			<artifactId>user-log</artifactId>
			<version>${project.version}</version>
		</dependency>
		
		<dependency>
			<groupId>${project.groupId}</groupId>
			<artifactId>user-core</artifactId>
			<version>${project.version}</version>
		</dependency>
		
	</dependencies>
</project>

    此時細心的讀者會發現在user-service的pom文件中出現${project.groupId}和${project.version}的寫法,這是Maven的內置隱式變量,常用的如下介紹:

${basedir} 項目根目錄
${project.build.directory} 構建目錄,缺省爲target
${project.build.outputDirectory} 構建過程輸出目錄,缺省爲target/classes
${project.build.finalName} 產出物名稱,缺省爲${project.artifactId}-${project.version}
${project.packaging} 打包類型,缺省爲jar
${project.xxx} 當前pom文件的任意節點的內容(這裏所使用到的)

注意:

    在完成user-service對user-log和user-service模塊的jar包引入的時候,一定要將這兩個模塊進行install處理,這樣在user-service中才可以訪問到前兩個模塊的jar包。

傳遞依賴

此時打開user-service的pom的dependency  hierarchy圖,如圖所示:


                      圖8

    會發現在user-log中使用log4j-1.2.4.jar而user-core中使用log4j-1.2.14.jar,但user-service包含user-log和user-core後,所使用的是log4j-1.2.4,爲什麼不使用新的版本呢?

    這是因爲我在user-service中將user-log寫在了user-core前面。但難道誰寫在前面就在前面了嗎?

    那我就將這兩個配置調換一下,得到的圖如圖9所示


                     圖9

    再看log4j變成了log4j-1.2.14.jar(圖中沒有標出,但不難看出),那確實是這樣嗎?然後看圖8中dom4j是1.5版本,在圖9中調換過位置後還是1.5版本,怎麼回事?細心的讀者會發現log4j是出於user-core和user-log的同一級別,而dom4j在user-core和user-log卻不是在同一級別。

奧,我明白了,原來是這麼一回事:

結論:

1、當依賴的級別相同時,引入最先導入的jar包

2、當依賴級別不同時候,引入級別最近的jar包

那我偏要使用dom4j1.6.1的版本,那怎麼辦呢?

排除依賴

    Maven很智能,在此提供一個元素,exclusion,只要在不想要的模塊中添加此元素,比如不想要user-log的dom4j1.5版本,則只要在user-service中這樣編寫即可:

<dependency>
			<groupId>${project.groupId}</groupId>
			<artifactId>user-log</artifactId>
			<version>${project.version}</version>
			<exclusions>
				<exclusion>
					<groupId>dom4j</groupId>
					<artifactId>dom4j</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
            此時在查看user-service的pom的dependency  hierarchy圖,發現已經成功使用dom4j1.6.1版本了,如圖所示


                     圖10

依賴範圍(scope)

    讀者還會發現,在圖8,9,10中,每個jar後都有類似[compile]的標識,這是什麼意思呢?這裏將引入Maven的依賴範圍概念。

    什麼是依賴範圍呢?

    引入:

    Maven在編譯主代碼的時候需要使用一套classpath,在編譯和執行測試的時候會使用另一套classpath,實際運行項目的時候,又會使用一套classpath。
    依賴範圍就是用來控制依賴與這三種classpath(編譯classpath、測試classpath、運行classpath)的關係,

    Maven有以下幾種依賴範圍:
    compile: 編譯依賴範圍。

    如果沒有指定,就會默認使用該依賴範圍。使用此依賴範圍的Maven依賴,對於編譯、測試、運行三種classpath都有效。
 
    test: 測試依賴範圍。

    使用此依賴範圍的Maven依賴,只對於測試classpath有效,在編譯主代碼或者運行項目的使用時將無法使用此類依賴。典型的例子就是JUnit,它只有在編譯測試代碼及運行測試的時候才需要。這也是本文的pom文件中爲何junit的scope是使用test範圍的原因。
 
    provided: 已提供依賴範圍。

    使用此依賴範圍的Maven依賴,對於編譯和測試classpath有效,但在運行時無效。典型的例子是servlet-api,編譯和測試項目的時候需要該依賴,但在運行項目的時候,由於容器已經提供,就不需要Maven重複地引入一遍。
 
    runtime: 運行時依賴範圍。

使用此依賴範圍的Maven依賴,對於測試和運行classpath有效,但在編譯主代碼時無效。典型的例子是JDBC驅動實現,項目主代碼的編譯只需要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候才需要實現上述接口的具體JDBC驅動。

   

    注意:以上四種範圍是開發中常用的配置,而以下兩種都是不要求的,使用的很少,瞭解即可

    system: 系統依賴範圍。

該依賴與三種classpath的關係,和provided依賴範圍完全一致。但是,使用system範圍依賴時必須通過systemPath元素顯式地指定依賴文件的路徑。由於此類依賴不是通過Maven倉庫解析的,而且往往與本機系統綁定,可能造成構建的不可移植,因此應該謹慎使用。

    import(Maven 2.0.9及以上): 導入依賴範圍。

總結

    至此,對於Maven的依賴性已經講解差不多了,餘下的在開發中很少使用到,所以掌握以上內容已經足夠使用了,而且Maven的依賴算是Maven的學習中的一個難點,因此需要自己手動創建項目進行測試驗證。

    在此,一樣恭祝大家學習愉快,新年快樂!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章