Maven使用簡易教程
一、Maven介紹我們在開發項目的過程中,會使用一些開源框架、第三方的工具等等,這些都是以jar包的方式被項目所引用,並且有些jar包還會依賴其他的jar包,我們同樣需要添加到項目中,所有這些相關的jar包都會作為項目的依賴。通常,一個Java EE項目所依賴的jar包會有很多。然而,這還並非是主要問題,在管理這些jar包過程中,jar包的版本往往是最令人頭疼的問題。選擇一個jar包的版本,需要考慮它所依賴的jar包是否支持這個版本,並且還需要確認依賴它的jar包能不能對這個版本兼容。所以,在過去的構建項目過程中,整理出這麼一堆能讓項目正常運行的jar包之後,這個lib目錄就會變為禁區。jar包版本更新了,我們也很少會自找麻煩去觸碰它。至於是不是存在冗餘的jar包?能正常運行就好了嘛。。。。
Maven的出現,解決了開發過程中的這一難題。它可以對項目依賴的jar包進行管理,可以讓你的項目保持基本的依賴,排除冗餘jar包,並且可以讓你非常輕鬆的對依賴的jar包進行版本升級。而這些僅僅是Maven最基本的功能,它可以在這基礎上對項目進行清理、編譯、測試、打包、發布等等構建項目的工作。
可以說,Maven是現在Java社區中最強大的項目管理和項目構建工具,而更加值得慶幸的是,這樣一個強大的工具,它的使用也是非常簡單的。
現在,JavaEE項目使用的開源軟件都可以通過Maven來獲取,並且,越來越多的公司也開始使用Maven來管理構建項目了。
二、Maven下載安裝
1、配置Java運行環境
Maven依賴Java運行環境,因此使用Maven之前需要配置Java的運行環境。下載並安裝JDK,配置JDK的環境變量:
JAVA_HOME=D:\Dev\Tool\Java\jdk1.6.0_38
在path中加入%JAVA_HOME%\bin;
2、安裝Maven
下載Maven最新版本的二進製zip壓縮包就可以,如:apache-maven-3.0.5-bin.zip
下載完成後,解壓,例如我們把解壓後的文件夾放在D:\Dev\Tool\目錄下。
然後,將Maven的bin目錄添加到path環境變量中,我們這裏就是這個目錄:D:\Dev\Tool\apache-maven-3.0.4\bin
在Windows命令提示符下,輸入mvn -v測試一下,如圖:

這樣,maven就安裝完成了,就是這麼簡單。接下來我們先來了解一下Maven是如何來管理項目的。
三、Maven依賴管理
前麵講了,Maven最核心的就是對依賴jar包的管理,那麼它是通過什麼方式來進行管理的呢?
Maven要求每一個jar包都必須明確定義自己的坐標,Maven就是通過這個坐標來查找管理這些jar包的。
在Maven中,一個jar包的坐標是由它的groupId、artifactId、version這些元素來定義的。例如:
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.8</version>
<packaging>jar</packaging>
groupId:表明其所屬組織或公司及其所屬項目,命名規則為組織或公司域名反轉加項目名稱。
artifactId:項目的模塊名,通常與實際項目名稱一致。模塊的命名通常為項目名前綴加模塊名。
version:當前項目的版本號。
packaging:定義項目的打包方式,可選值有jar、war、pom。默認為jar
注::一個組織或公司都會有很多的項目,而每個項目下都會劃分多個模塊,在開發中我們可以靈活選擇依賴某個模塊。而Maven管理的jar包基本都是模塊性質的項目構建出的jar包。所以,artifactId通常都是模塊名,而不是項目名稱。項目名稱是和組織名稱組合作為groupId來使用的。
上麵的配置定義了一個Maven項目的坐標,而如果在項目中依賴這個項目時,同樣是利用它的坐標來指定依賴。例如:
<project>
...
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.8</version>
</dependency>
</dependencies>
...
</project>
Maven的配置文件中dependencies元素包含了所有依賴的jar包,每一個jar包依賴使用dependency元素定義。
在聲明一個jar包依賴時,除了指定groupId、artifactId、version這三項基本坐標外,還可以使用使用以下元素進行配置:
scope元素:指定依賴的範圍
exclusions元素:排除傳遞性依賴
Maven有以下幾種依賴範圍:
compile:編譯依賴範圍(默認值),依賴在編譯、測試、運行期間都有效。
test:測試依賴範圍,隻對測試的classpath有效,在編譯或運行時無法使用指定為test的依賴包。
provided:已提供的依賴範圍,隻對編譯和測試的classpath有效,運行期間不會使用這個依賴。例如servlet-api,在運行時容器已經提供,不需要再重複引入。
runtime:運行時依賴範圍,編譯時無效,隻在測試和運行時使用這個依賴。
system:係統依賴範圍,和provided範圍一致,但是provided是使用容器提供依賴,system是使用係統提供依賴,需要指定依賴文件路徑。
傳遞性依賴,是指依賴包對其他包的依賴,比如,我們依賴struts2-core,而strtus2-core需要依賴xwork-core、ognl等,Maven會將這些傳遞性依賴同時引入項目之中。這也是Maven的一大優點,簡化了我們對jar包依賴的管理。而有時我們希望替換某個傳遞性依賴時,就需要使用exclusions排除掉這個傳遞性依賴,然後再添加我們自己要替換的依賴包。
例如,如下一個Maven的配置文件,pom.xml:
[html]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.boya.spring</groupId>
<artifactId>spring_ioc</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>${project.artifactId}</name>
<description>Spring Ioc Sample</description>
<dependencies>
<!-- spring start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<!-- logging start -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>log4jdbc</groupId>
<artifactId>log4jdbc4</artifactId>
<version>1.2</version>
</dependency>
<!--Test start-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
四、Maven倉庫
Maven通過項目定義的坐標來管理這些依賴,而這些依賴的物理文件是通過Maven的倉庫來統一管理的。
對於一個依賴坐標,它會按照如下方式反映到Maven的倉庫中。
1、將groupId轉化為路徑:將groupId中的包名分隔符(.)轉換成路徑分隔符(/)。對於上麵的例子就是 org.apache.struts -> org/apache/struts/
2、將artifactId轉化為路徑:在groupId轉化的路徑基礎上連接artifactId。生成路徑為: org/apache/struts/struts2-core/
3、將verion轉化為路徑:在artifactId轉化的路徑基礎上連接version。生成路徑為: org/apache/struts/struts2-core/2.3.8/
4、根據artifactId和version生成依賴包文件名:上例就是 struts2-core-2.3.8
5、根據依賴的打包方式確定文件的擴展名。對於上例它的擴展名就是.jar
這樣根據路徑和文件名就找到了這個物理文件在倉庫中的位置:org/apache/struts/struts2-core/2.3.8/struts2-core-2.3.8.jar
Maven的倉庫分為本地倉庫和遠程倉庫。
本地倉庫:是Maven在我們本機設置的倉庫目錄,默認目錄為當前用戶目錄下的.m2/repository.
遠程倉庫包括中央倉庫、私服、其他公共倉庫。
中央倉庫是Maven提供的遠程倉庫,地址是:https://repo.maven.apache.org/maven2
私服是我們為了節省帶寬和時間,提升效率,在局域網架設的私有Maven倉庫。
Maven在根據依賴坐標查找依賴時,首先會從本地倉庫查找該依賴包,當本地倉庫中沒有這個依賴包時,Maven會從中央倉庫查找依賴,並下載到本地倉庫。最後,在我們項目的classpath中引用本地倉庫的依賴包路徑。
例如,當項目隻依賴strtus2-core這個依賴包時,會生成這樣的classpath文件:
[html]
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java" output="/src/main/webapp/WEB-INF/classes" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" output="/src/main/webapp/WEB-INF/classes" excluding="**/*.java"/>
<classpathentry kind="output" path="src/main/webapp/WEB-INF/classes"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="com.genuitec.eclipse.j2eedt.core.J2EE14_CONTAINER"/>
<classpathentry kind="var" path="M2_REPO/org/apache/struts/struts2-core/2.3.8/struts2-core-2.3.8.jar" />
<classpathentry kind="var" path="M2_REPO/org/apache/struts/xwork/xwork-core/2.3.8/xwork-core-2.3.8.jar" />
<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar" />
<classpathentry kind="var" path="M2_REPO/ognl/ognl/3.0.6/ognl-3.0.6.jar" />
<classpathentry kind="var" path="M2_REPO/javassist/javassist/3.11.0.GA/javassist-3.11.0.GA.jar" />
<classpathentry kind="var" path="M2_REPO/asm/asm/3.3/asm-3.3.jar"/>
<classpathentry kind="var" path="M2_REPO/asm/asm-commons/3.3/asm-commons-3.3.jar"/>
<classpathentry kind="var" path="M2_REPO/asm/asm-tree/3.3/asm-tree-3.3.jar"/>
<classpathentry kind="var" path="M2_REPO/org/freemarker/freemarker/2.3.19/freemarker-2.3.19.jar" />
<classpathentry kind="var" path="M2_REPO/commons-fileupload/commons-fileupload/1.2.2/commons-fileupload-1.2.2.jar" />
<classpathentry kind="var" path="M2_REPO/commons-io/commons-io/2.3/commons-io-2.3.jar" />
</classpath>
其中,本地倉庫目錄會使用M2_REPO變量表示,因此IDE環境未配置該變量時,需在IDE中添加這個變量的classpath。
五、聚合與繼承
一個項目通常存在多個模塊,每個模塊都是作為一個獨立的工程存在。通過Maven配置文件可以把多個模塊聚合在一起進行編譯發布,並且它的聚合非常簡單隻需要使用<modules>元素添加模塊就可以完成聚合。我們參考struts2的pom.xml文件來看一下聚合的配置方式:
[html]
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.3.8</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
<name>Webapps</name>
<modules>
<module>blank</module>
<module>mailreader</module>
<module>portlet</module>
<module>showcase</module>
<module>rest-showcase</module>
</modules>
....
</project>
另外,在這個項目的個各模塊間通常是存在引用關係,並且每個模塊會引用一些相同的依賴,Maven也提供了繼承的機製來管理這些共同的依賴。你可以編寫一個pom.xml文件作為父級pom配置,各個模塊在自己的pom.xml中繼承父級pom文件,就像上麵的示例那樣,使用<parent>元素標識繼承的父級pom文件。
父級pom文件的編寫:
1、父級pom文件的packaging必須是pom,它需要作為pom文件發布以便子pom繼承
2、在父級pom可以使用<dependencyManagement>配置依賴管理。在<dependencyManagement>下的依賴聲明不會引入實際依賴,但是可以讓子模塊繼承依賴配置。例如,在子模塊中我們隻標識依賴的groupId和artifactId,它就可以根據父類的依賴管理獲取這個依賴的version及exclussions等配置。
3、在父級pom中可以使用<pluginManagement>配置插件管理。作用和<dependencyManagement>類似,隻不過一個管理依賴一個管理插件。
子模塊pom文件的編寫:
1、需要使用<parent>元素標識繼承的父pom
2、可以使用<relativePath>標識父級pom的物理路徑,子模塊會直接從指定的路徑加載父級pom文件,未指定該元素時,子模塊將根據父級pom的坐標從Maven倉庫查找
3、子模塊pom可以繼承父級pom中除artifactId之外的大部分配置,因此子模塊的groupId、version以及依賴的version都可以省略。
六、Maven腳本使用
現在大部分IDE都有插件支持Maven,使用插件可以方便的構建Maven項目,如果IDE不支持Maven插件或未安裝Maven插件也可以使用一個簡單的批處理腳本來完成Maven項目的構建。
例如,保存下麵內容,存儲為bat格式的批處理文件
cd %~dp0
call mvn eclipse:clean eclipse:eclipse
pause
運行該文件,就會自動根據該目錄下的pom.xml生成該項目的eclipse開發環境配置。
在後麵的教程及示例中我都是使用Maven來構建的,pom.xml的示例可以參考我後麵的教程和代碼示例。
最後更新:2017-04-03 08:26:25