前言
項目中用到了maven,而且用到的內容不像利用maven/eclipse搭建ssm(spring+spring mvc+mybatis)用的那么簡單;maven的核心是pom.xml,那么我就它來談談那些不同的地方;
給我印象最深的就是如下四個元素:modules、parent、properties、import。
路漫漫其修遠兮,吾將上下而求索!
github:https://github.com/youzhibing
碼雲(gitee):https://gitee.com/youzhibing
modules
從字面意思來說,module就是模塊,而pom.xml中的modules也正是這個意思,用來管理同個項目中的各個模塊;如果maven用的比較簡單,或者說項目的模塊在pom.xml沒進行划分,那么此元素是用不到的;不過一般大一點的項目是要用到的。
需求場景
如果我們的項目分成了好幾個模塊,那么我們構建的時候是不是有幾個模塊就需要構建幾次了(到每個模塊的目錄下執行mvn命令)?當然,你逐個構建沒問題,但是非要這么麻煩的一個一個的構建嗎,那么簡單的做法就是使用聚合,一次構建全部模塊。
具體實現
a.既然使用聚合,那么就需要一個聚合的載體,先創建一個普通的maven項目account-aggregator,如下圖:
因為是個聚合體,僅僅負責聚合其他模塊,那么就只需要上述目錄,該刪除的就刪了;注意的是pom文件的書寫(紅色標明的):
<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.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Account Aggrregator</name> <url>http://maven.apache.org</url> <modules>
<!-- 模塊都寫在此處 --> <module>account-register</module> <module>account-persist</module> </modules> </project>
b.創建子模account-register、account-persist:右擊account-aggregator,new --> other --> Maven,選擇Maven Module,創建moven模塊。
c.創建完成后,項目結構如下,那么此時account-aggregator可以收縮起來了,我們操作具體子模塊就好了。
d.注意點,當我們打開包結構的子模塊的pom文件時,發現離預期的多了一些內容,我們坐下處理就好了。
e.那么編碼完了之后,我們只需要構建account-aggregator就好了,所有的子模塊都會構建。
parent
繼承,和java中的繼承相當,作用就是復用
需求場景
若每個子模塊都都用的了spring,那么我們是不是每個子模塊都需要單獨配置spring依賴了?,這么做是可以的,但是我們有更優的做法,那就是繼承,用parent來實現。
具體實現
a.配置父pom.xml
我就用聚合pom來做父pom,配置子模塊的公共依賴。
父(account-aggregator)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.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Account Aggrregator</name> <url>http://maven.apache.org</url> <modules> <!-- 模塊都寫在此處 --> <module>account-register</module> <module>account-persist</module> </modules> <dependencies> <!-- 配置共有依賴 --> <!-- spring 依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.0.2.RELEASE</version> </dependency> <!-- junit 依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> </dependencies> </project>
b.account-register的pom.xml :

<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> <!-- 與不配置一樣,默認就是尋找上級目錄下得pom.xml --> </parent> <artifactId>account-register</artifactId> <name>account-register</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 配置自己獨有依賴 --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.3</version> </dependency> <dependency> <groupId>com.icegreen</groupId> <artifactId>greenmail</artifactId> <version>1.4.1</version> <scope>test</scope> </dependency> </dependencies> </project>
c.account-persist的pom.xml :

<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>account-persist</artifactId> <name>account-persist</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 配置自己獨有依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.16</version> </dependency> </dependencies> </project>
d.依賴的jar包全部ok,需要做的則是在各個模塊中進行代碼開發了!
依賴管理
繼承可以消除重復,那是不是就沒有問題了? 答案是存在問題,假設將來需要添加一個新的子模塊account-util,該模塊只是提供一些簡單的幫助工具,不需要依賴spring、junit,那么繼承后就依賴上了,有沒有什么辦法了? 有,maven已經替我們想到了,那就是dependencyManagement元素,既能讓子模塊繼承到父模塊的依賴配置,又能保證子模塊依賴使用的靈活性。在dependencyManagement元素下得依賴聲明不會引入實際的依賴,不過它能夠約束dependencies下的依賴使用。
在父pom.xml中配置dependencyManagement元素

<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.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Account Aggrregator</name> <url>http://maven.apache.org</url> <modules> <!-- 模塊都寫在此處 --> <module>account-register</module> <module>account-persist</module> </modules> <dependencyManagement> <dependencies> <!-- 配置共有依賴 --> <!-- spring 依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.0.2.RELEASE</version> </dependency> <!-- junit 依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> </project>
account-persist的pom.xml(account-register也一樣) :

<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>account-persist</artifactId> <name>account-persist</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- spring 依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- junit 依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.16</version> </dependency> </dependencies> </project>
使用這種依賴管理機制似乎不能減少太多的POM配置,就少了version(junit還少了個scope),感覺沒啥作用呀;其實作用還是挺大的,父POM使用dependencyManagement能夠統一項目范圍中依賴的版本,當依賴版本在父POM中聲明后,子模塊在使用依賴的時候就無須聲明版本,也就不會發生多個子模塊使用版本不一致的情況,幫助降低依賴沖突的幾率。如果子模塊不聲明依賴的使用,即使該依賴在父POM中的dependencyManagement中聲明了,也不會產生任何效果。
import
import只在dependencyManagement元素下才有效果,作用是將目標POM中的dependencyManagement配置導入並合並到當前POM的dependencyManagement元素中,如下就是講account-aggregator中的dependencyManagement配置導入並合並到當前POM中。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.youzhibing.account</groupId>
<artifactId>account-aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
properties
通過<properties>元素用戶可以自定義一個或多個Maven屬性,然后在POM的其他地方使用${屬性名}的方式引用該屬性,這種做法的最大意義在於消除重復和統一管理。
Maven總共有6類屬性,內置屬性、POM屬性、自定義屬性、Settings屬性、java系統屬性和環境變量屬性;
內置屬性
兩個常用內置屬性 ${basedir} 表示項目跟目錄,即包含pom.xml文件的目錄;${version} 表示項目版本
pom屬性
用戶可以使用該類屬性引用POM文件中對應元素的值。如${project.artifactId}就對應了<project> <artifactId>元素的值,常用的POM屬性包括:
${project.build.sourceDirectory}:項目的主源碼目錄,默認為src/main/java/
${project.build.testSourceDirectory}:項目的測試源碼目錄,默認為src/test/java/
${project.build.directory} : 項目構建輸出目錄,默認為target/
${project.outputDirectory} : 項目主代碼編譯輸出目錄,默認為target/classes/
${project.testOutputDirectory}:項目測試主代碼輸出目錄,默認為target/testclasses/
${project.groupId}:項目的groupId
${project.artifactId}:項目的artifactId
${project.version}:項目的version,與${version} 等價
${project.build.finalName}:項目打包輸出文件的名稱,默認為${project.artifactId}-${project.version}
自定義屬性
如下account-aggregator的pom.xml,那么繼承了此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.youzhibing.account</groupId> <artifactId>account-aggregator</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Account Aggrregator</name> <url>http://maven.apache.org</url> <modules> <!-- 模塊都寫在此處 --> <module>account-register</module> <module>account-persist</module> <module>account-another</module> </modules> <properties> <!-- 定義 spring版本號 --> <spring.version>4.0.2.RELEASE</spring.version> <junit.version>4.7</junit.version> </properties> <dependencyManagement> <dependencies> <!-- 配置共有依賴 --> <!-- spring 依賴 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- junit 依賴 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> </project>
settings屬性
與POM屬性同理,用戶使用以settings. 開頭的屬性引用settings.xml文件中的XML元素的值。
Java系統屬性
所有java系統屬性都可以用Maven屬性引用,如${user.home}指向了用戶目錄。
環境變量屬性
所有環境變量屬性都可以使用以env. 開頭的Maven屬性引用,如${env.JAVA_HOME}指代了JAVA_HOME環境變量的的值。
聚合與繼承的關系
1.聚合主要是為了方便快速構建項目,繼承主要是為了消除重復配置;
2.對於聚合模塊而言,它知道有哪些被聚合的模塊,但那些被聚合的模塊不知道這個聚合模塊的存在;對於繼承的父pom而言,它不知道有哪些子模塊繼承它,但那些子模塊都必須知道自己的父POM是什么;
3.聚合POM與繼承中的父POM的packaging都必須是pom;同時,聚合模塊與繼承中的父模塊除了POM外,都沒有實際的內容
結束語
maven越來越流行,這方面的資料也是越來越多,《Maven實戰》給我的感覺就相當不錯,本博客的內容大多取自其中;網上資料也越來越多,就博客園中就有不少;
最后強調一點:看了是好,實踐更好,寫博客記錄下來那是最好!