小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Maven管理依賴

 旭龍 2011-06-10

有人認為Maven是一個依賴管理工具,當然這種想法是錯誤的(確切的說Maven是一個項目管理工具,貫穿了整個項目生命周期,編譯,測試,打包,發(fā)布...),但Maven給人造成這種錯誤的印象也是有原因的,因為Maven的依賴管理十分強大,用好了Maven,你不再需要面對一大堆jar感到頭大,依賴沖突,無用依賴等問題也能夠得到有效的防止和解決。本節(jié)介紹如何用好Maven的依賴管理。

 

最簡單的依賴

依賴是使用Maven坐標來定位的,而Maven坐標主要由GAV(groupId, artifactId, version)構(gòu)成。因此,使用任何一個依賴之間,你都需要知道它的Maven坐標,關(guān)于如何尋找Maven坐標,《搜索Maven倉庫》 一文可以幫助你。

最簡單的依賴如:

Xml代碼
  1. <dependency>  
  2.   <groupId>junit</groupId>  
  3.   <artifactId>junit</artifactId>  
  4.   <version>4.4</version>  
  5. </dependency>  
<dependency>  <groupId>junit</groupId>  <artifactId>junit</artifactId>  <version>4.4</version></dependency>

上例中我們聲明了一個對junit的依賴,它的groupId是junit, artifactId是junit, version是4.4。這一組GAV構(gòu)成了一個Maven坐標,基于此,Maven就能在本地或者遠程倉庫中找到對應的junit-4.4.jar文件。

 

依賴歸類

隨著項目的增大,你的依賴越來越多,比如說你依賴了一堆spring的jar,有org.spring.framework:spring-core, org.spring.framework:beans, org.spring.framework:spring-web, org.spring.framework:spring-mock。它們的groupId是相同的,artifactId不同。為了管理其版本,你對它們進行過統(tǒng)一的升級,逐個的將version改成了最新版。但是,顯然,當POM很大的時候你說不定會犯錯誤,而當版本不一致的時候,一些詭異的兼容性問題就可能出現(xiàn)。

對此,Maven有它的解決方案:

Xml代碼
  1. <dependencies>  
  2.   <dependency>  
  3.     <groupId>org.spring.framework</groupId>  
  4.     <artifactId>spring-core</artifactId>  
  5.     <version>${spring.version}</version>  
  6.   </dependency>  
  7.   <dependency>  
  8.     <groupId>org.spring.framework</groupId>  
  9.     <artifactId>spring-beans</artifactId>  
  10.     <version>${spring.version}</version>  
  11.   </dependency>  
  12.   <dependency>  
  13.     <groupId>org.spring.framework</groupId>  
  14.     <artifactId>spring-web</artifactId>  
  15.     <version>${spring.version}</version>  
  16.   </dependency>  
  17.   <dependency>  
  18.     <groupId>org.spring.framework</groupId>  
  19.     <artifactId>spring-mock</artifactId>  
  20.     <version>${spring.version}</version>  
  21.   </dependency>  
  22. </dependencies>  
  23.   
  24. <properties>  
  25.   <spring.version>2.5</spring.version>  
  26. </properties>  
<dependencies>  <dependency>    <groupId>org.spring.framework</groupId>    <artifactId>spring-core</artifactId>    <version>${spring.version}</version>  </dependency>  <dependency>    <groupId>org.spring.framework</groupId>    <artifactId>spring-beans</artifactId>    <version>${spring.version}</version>  </dependency>  <dependency>    <groupId>org.spring.framework</groupId>    <artifactId>spring-web</artifactId>    <version>${spring.version}</version>  </dependency>  <dependency>    <groupId>org.spring.framework</groupId>    <artifactId>spring-mock</artifactId>    <version>${spring.version}</version>  </dependency></dependencies><properties>  <spring.version>2.5</spring.version></properties>

這里我們定義了一個Maven屬性,其名稱為spring.version,值是2.5。在這個POM中,我們就能用${spring.version}的方式來引用該屬性。我們看到,所有spring相關(guān)的依賴的version元素現(xiàn)在都成了${spring.version},當Maven運行的時候,它會自動用值2.5來替換這個引用。

當我們需要升級spring的時候,只要更改一個地方便可,而且,你現(xiàn)在能很高的保證所有的spring依賴包都是同一個版本。

 

依賴范圍(scope)

本文的第一個例子其實是有漏洞的,對于Junit,一般來說你只有在運行測試的時候需要它,也就是說,它對于src/main/java的classpath沒什么意義,并且,將Junit的jar文件打入最終的發(fā)布包也不是好事,這無謂的增加了發(fā)布包的大小。

其實我們應該這樣做:

Xml代碼
  1. <dependency>  
  2.   <groupId>junit</groupId>  
  3.   <artifactId>junit</artifactId>  
  4.   <version>4.4</version>  
  5.   <scope>test</test>  
  6. </dependency>  
<dependency>  <groupId>junit</groupId>  <artifactId>junit</artifactId>  <version>4.4</version>  <scope>test</test></dependency>

于是,junit對于主源碼classpath不可用,對于測試源碼classpath可用,不會被打包。

再舉個例子,在開發(fā)javaee應用的時候我們一定會用到servlet-api,它對于主源碼和測試源碼都是必要的,因為我們的代碼中會引入servlet-api的包。但是,在打包的時候,將其放入WAR包就會有問題,因為web容器會提供servlet-api,如果我們再將其打包就會造成依賴沖突,解決方案如下:

Xml代碼
  1. <dependency>  
  2.   <groupId>javax.servlet</groupId>  
  3.   <artifactId>servlet-api</artifactId>  
  4.   <version>2.4</version>  
  5.   <scope>provided</scope>  
  6. </dependency>  
<dependency>  <groupId>javax.servlet</groupId>  <artifactId>servlet-api</artifactId>  <version>2.4</version>  <scope>provided</scope></dependency>

將依賴范圍設(shè)置成provided,就意味著該依賴對于主源碼classpath,以及測試classpath可用,但不會被打包。這正是servlet-api所需要的。

這里歸納一下主要的依賴范圍以及作用:

 

依賴范圍(scope) 主源碼classpath可用 測試源碼classpath可用 會被打包
compile 缺省值 TRUE TRUE TRUE
test FALSE TRUE FALSE
runtime FALSE TRUE TRUE
provided TRUE TRUE FALSE

 

 

 

 

 

 

 

 

需要注意的是,當我們沒有聲明依賴范圍的時候,其默認的依賴范圍是compile。

 

分類器(classifer)

GAV是Maven坐標最基本最重要的組成部分,但GAV不是全部。還有一個元素叫做分類器(classifier),90%的情況你不會用到它,但有些時候,分類器非常不可或缺。

舉個簡單的例子,當我們需要依賴TestNG的時候,簡單的聲明GAV會出錯,因為TestNG強制需要你提供分類器,以區(qū)別jdk14和jdk15,我們需要這樣聲明對TestNG的依賴:

Xml代碼
  1. <dependency>  
  2.   <groupId>org.testng</groupId>  
  3.   <artifactId>testng</artifactId>  
  4.   <version>5.7</version>  
  5.   <classifier>jdk15</classifier>  
  6. </dependency>  
<dependency>  <groupId>org.testng</groupId>  <artifactId>testng</artifactId>  <version>5.7</version>  <classifier>jdk15</classifier></dependency>

你會注意到maven下載了一個名為testng-5.7-jdk15.jar的文件。其命名模式實際上是<artifactId>-<version>-<classifier>.<packaging>。理解了這個模式以后,你就會發(fā)現(xiàn)很多文件其實都是默認構(gòu)件的分類器擴展,如 myapp-1.0-test.jar, myapp-1.0-sources.jar。

分類器還有一個非常有用的用途是:我們可以用它來聲明對test構(gòu)件的依賴,比如,我們在一個核心模塊的src/test/java中聲明了一些基礎(chǔ)類,然后我們發(fā)現(xiàn)這些測試基礎(chǔ)類對于很多其它模塊的測試類都有用。沒有分類器,我們是沒有辦法去依賴src/test/java中的內(nèi)容的,因為這些內(nèi)容不會被打包到主構(gòu)件中,它們單獨的被打包成一個模式為<artifactId>-<version>-test.jar的文件。

我們可以使用分類器來依賴這樣的test構(gòu)件:

Xml代碼
  1. <dependency>  
  2.   <groupId>org.myorg.myapp</groupId>  
  3.   <artifactId>core</artifactId>  
  4.   <version>${project.version}</version>  
  5.   <classifier>test</classifier>  
  6. </dependency>  
<dependency>  <groupId>org.myorg.myapp</groupId>  <artifactId>core</artifactId>  <version>${project.version}</version>  <classifier>test</classifier></dependency>

理解了分類器,那么可供依賴的資源就變得更加豐富。

 

依賴管理(dependencyManagement)

當你只有一個Maven模塊的時候,你完全不需要看這個部分。但你心里應該清楚,只有一個Maven模塊的項目基本上只是個玩具。

實際的項目中,你會有一大把的Maven模塊,而且你往往發(fā)現(xiàn)這些模塊有很多依賴是完全項目的,A模塊有個對spring的依賴,B模塊也有,它們的依賴配置一模一樣,同樣的groupId, artifactId, version,或者還有exclusions, classifer。細心的分會發(fā)現(xiàn)這是一種重復,重復就意味著潛在的問題,Maven提供的dependencyManagement就是用來消除這種重復的。

正確的做法是:

1. 在父模塊中使用dependencyManagement配置依賴

2. 在子模塊中使用dependencies添加依賴

dependencyManagement實際上不會真正引入任何依賴,dependencies才會。但是,當父模塊中配置了某個依賴之后,子模塊只需使用簡單groupId和artifactId就能自動繼承相應的父模塊依賴配置。

這里是一個來自于《Maven權(quán)威指南》的例子:

父模塊中如此聲明:

Xml代碼
  1. <project>  
  2.   <modelVersion>4.0.0</modelVersion>  
  3.   <groupId>org.sonatype.mavenbook</groupId>  
  4.   <artifactId>a-parent</artifactId>  
  5.   <version>1.0.0</version>  
  6.   ...  
  7.   <dependencyManagement>  
  8.     <dependencies>  
  9.       <dependency>  
  10.         <groupId>mysql</groupId>  
  11.         <artifactId>mysql-connector-java</artifactId>  
  12.         <version>5.1.2</version>  
  13.       </dependency>  
  14.       ...  
  15.     <dependencies>  
  16.   </dependencyManagement>  
<project>  <modelVersion>4.0.0</modelVersion>  <groupId>org.sonatype.mavenbook</groupId>  <artifactId>a-parent</artifactId>  <version>1.0.0</version>  ...  <dependencyManagement>    <dependencies>      <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>5.1.2</version>      </dependency>      ...    <dependencies>  </dependencyManagement>

子模塊中如此聲明:

Xml代碼
  1. <project>  
  2.   <modelVersion>4.0.0</modelVersion>  
  3.   <parent>  
  4.     <groupId>org.sonatype.mavenbook</groupId>  
  5.     <artifactId>a-parent</artifactId>  
  6.     <version>1.0.0</version>  
  7.   </parent>  
  8.   <artifactId>project-a</artifactId>  
  9.   ...  
  10.   <dependencies>  
  11.     <dependency>  
  12.       <groupId>mysql</groupId>  
  13.       <artifactId>mysql-connector-java</artifactId>  
  14.     </dependency>  
  15.   </dependencies>  
  16. </project>  
<project>  <modelVersion>4.0.0</modelVersion>  <parent>    <groupId>org.sonatype.mavenbook</groupId>    <artifactId>a-parent</artifactId>    <version>1.0.0</version>  </parent>  <artifactId>project-a</artifactId>  ...  <dependencies>    <dependency>      <groupId>mysql</groupId>      <artifactId>mysql-connector-java</artifactId>    </dependency>  </dependencies></project>

你依賴配置越復雜,依賴管理所起到的作用就越大,它不僅能夠幫助你簡化配置,它還能夠幫你鞏固依賴配置,也就是說,在整個項目中,對于某個構(gòu)件(如mysql)的依賴配置只有一種,這樣就能避免引入不同版本的依賴,避免依賴沖突。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多