maven

Fork me on GitHub

Maven入門教程

 

概念

Maven是什麼

Maven 是一個項目管理工具。它負責管理項目開發過程中的幾乎所有的東西。

版本

maven有自己的版本定義和規則

構建

maven支持許多種的應用程序類型,對於每一種支持的應用程序類型都定義好了一組構建規則和工具集。

輸出物管理

maven可以管理項目構建的產物,並將其加入到用戶庫中。這個功能可以用於項目組和其他部門之間的交付行爲

依賴關係

maven對依賴關係的特性進行細緻的分析和劃分,避免開發過程中的依賴混亂和相互污染行爲

文檔和構建結果

maven的site命令支持各種文檔信息的發佈,包括構建過程的各種輸出,javadoc,產品文檔等。

項目關係

一個大型的項目通常有幾個小項目或者模塊組成,用maven可以很方便地管理

移植性管理

maven可以針對不同的開發場景,輸出不同種類的輸出結果

 

Maven的生命週期

maven把項目的構建劃分爲不同的生命週期(lifecycle)。粗略一點的話,它這個過程(phase)包括:編譯、測試、打包、集成測試、驗證、部署。maven中所有的執行動作(goal)都需要指明自己在這個過程中的執行位置,然後maven執行的時候,就依照過程的發展依次調用這些goal進行各種處理。

這個也是maven的一個基本調度機制。一般來說,位置稍後的過程都會依賴於之前的過程。當然,maven同樣提供了配置文件,可以依照用戶要求,跳過某些階段。

 

Maven的標準工程結構

Maven的標準工程結構如下:

|-- pom.xml(maven的核心配置文件)

|-- src

|-- main

|   `-- java(java源代碼目錄)

|   `-- resources(資源文件目錄)

|-- test

        `-- java(單元測試代碼目錄)

|-- target(輸出目錄,所有的輸出物都存放在這個目錄下)

    |--classes(編譯後的class文件存放處)

 

Maven的"約定優於配置"

所謂的"約定優於配置",在maven中並不是完全不可以修改的,他們只是一些配置的默認值而已。但是除非必要,並不需要去修改那些約定內容。maven默認的文件存放結構如下:

每一個階段的任務都知道怎麼正確完成自己的工作,比如compile任務就知道從src/main/java下編譯所有的java文件,並把它的輸出class文件存放到target/classes中。

對maven來說,採用"約定優於配置"的策略可以減少修改配置的工作量,也可以降低學習成本,更重要的是,給項目引入了統一的規範。

 

Maven的版本規範

maven使用如下幾個要素來唯一定位某一個輸出物:

groudId

團體、組織的標識符。團體標識的約定是,它以創建這個項目的組織名稱的逆向域名(reverse domain name)開頭。一般對應着JAVA的包的結構。例如org.apache

artifactId 

單獨項目的唯一標識符。比如我們的tomcat, commons等。不要在artifactId中包含點號(.)。

version 

一個項目的特定版本。

packaging 

項目的類型,默認是jar,描述了項目打包後的輸出。類型爲jar的項目產生一個JAR文件,類型爲war的項目產生一個web應用。

 

maven有自己的版本規範,一般是如下定義 <major version>.<minor version>.<incremental version>-<qualifier> ,比如1.2.3-beta-01。要說明的是,maven自己判斷版本的算法是major,minor,incremental部分用數字比較,qualifier部分用字符串比較,所以要小心alpha-2和alpha-15的比較關係,最好用 alpha-02的格式。

maven在版本管理時候可以使用幾個特殊的字符串 SNAPSHOT,LATEST,RELEASE。比如"1.0-SNAPSHOT"。各個部分的含義和處理邏輯如下說明:

SNAPSHOT

這個版本一般用於開發過程中,表示不穩定的版本。

LATEST

指某個特定構件的最新發布,這個發佈可能是一個發佈版,也可能是一個snapshot版,具體看哪個時間最後。

RELEASE

指最後一個發佈版。

 

安裝

官網下載地址

http://maven.apache.org/download.cgi

 

配置環境變量

注意:安裝maven之前,必須先確保你的機器中已經安裝了JDK。

1.解壓壓縮包(以apache-maven-3.3.9-bin.zip爲例)

2.添加環境變量MAVEN_HOME,值爲apache-maven-3.3.9的安裝路徑

3.在Path環境變量的變量值末尾添加%MAVEN_HOME%\bin

4.在cmd輸入mvn –version,如果出現maven的版本信息,說明配置成功。

 

本地倉儲配置

從中央倉庫下載的jar包,都會統一存放到本地倉庫中。我們需要配置本地倉庫的位置。

打開maven安裝目錄,打開conf目錄下的setting.xml文件。

可以參照下圖配置本地倉儲位置。

http://static.oschina.net/uploads/space/2013/0720/193952_I0KV_1162561.jpg

 

第一個Maven工程

在Eclipse中創建Maven工程

Maven插件

在Eclipse中創建Maven工程,需要安裝Maven插件。

一般較新版本的Eclipse都會帶有Maven插件,如果你的Eclipse中已經有Maven插件,可以跳過這一步驟。

點擊Help -> Eclipse Marketplace,搜索maven關鍵字,選擇安裝紅框對應的Maven插件。

 

Maven環境配置

點擊Window -> Preferences

如下圖所示,配置settings.xml文件的位置

 

創建Maven工程

File -> New -> Maven Project -> Next,在接下來的窗口中會看到一大堆的項目模板,選擇合適的模板。

接下來設置項目的參數,如下:

 

groupId是項目組織唯一的標識符,實際對應JAVA的包的結構,是main目錄裏java的目錄結構。

artifactId就是項目的唯一的標識符,實際對應項目的名稱,就是項目根目錄的名稱。

點擊Finish,Eclipse會創建一個Maven工程。

 

使用Maven進行構建

Eclipse中構建方式

在Elipse項目上右擊 -> Run As 就能看到很多Maven操作。這些操作和maven命令是等效的。例如Maven clean,等同於mvn clean命令。

你也可以點擊Maven build,輸入組合命令,並保存下來。如下圖:

 

Maven命令構建方式

當然,你也可以直接使用maven命令進行構建。

進入工程所在目錄,輸入maven命令就可以了。

如下圖

 

使用指導

如何添加外部依賴jar包

在Maven工程中添加依賴jar包,很簡單,只要在POM文件中引入對應的<dependency>標籤即可。

參考下例:

<projectxmlns="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.zp.maven</groupId>

  <artifactId>MavenDemo</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>jar</packaging>

  <name>MavenDemo</name>

  <url>http://maven.apache.org</url>

 

  <properties>

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

    <junit.version>3.8.1</junit.version>

  </properties>

 

  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>${junit.version}</version>

      <scope>test</scope>

    </dependency>

    <dependency>

      <groupId>log4j</groupId>

      <artifactId>log4j</artifactId>

      <version>1.2.12</version>

      <scope>compile</scope>

    </dependency>

  </dependencies>

</project>

 

<dependency>標籤最常用的四個屬性標籤:

groupId:項目組織唯一的標識符,實際對應JAVA的包的結構。

artifactId:項目唯一的標識符,實際對應項目的名稱,就是項目根目錄的名稱。

version:jar包的版本號。可以直接填版本數字,也可以在properties標籤中設置屬性值。

scope:jar包的作用範圍。可以填寫compile、runtime、test、system和provided。用來在編譯、測試等場景下選擇對應的classpath。

 

如何尋找jar包

可以在http://mvnrepository.com/站點搜尋你想要的jar包版本

例如,想要使用log4j,可以找到需要的版本號,然後拷貝對應的maven標籤信息,將其添加到pom .xml文件中。

 

如何使用Maven插件(Plugin)

要添加Maven插件,可以在pom.xml文件中添加<plugin>標籤。

<build>

  <plugins>

    <plugin>

      <groupId>org.apache.maven.plugins</groupId>

      <artifactId>maven-compiler-plugin</artifactId>

      <version>3.3</version>

      <configuration>

        <source>1.7</source>

        <target>1.7</target>

      </configuration>

    </plugin>

  </plugins>

</build>

<configuration>標籤用來配置插件的一些使用參數。

 

如何一次編譯多個工程

在Maven中,允許一個Maven Project中有多個Maven Module

1.創建maven父工程步驟:new-->other-->選擇maven project-->next-->勾選create a simple project-->next-->填寫Group Id、Artifact Id、Version --> packaging選擇pom-->finish。

2.創建maven子工程步驟:選中剛纔創建的父工程右鍵-->new-->other-->選擇maven module-->next-->勾選create a simple project-->填寫module name(其實就是artifact id)-->next-->GAV繼承父工程-->packaging選擇你需要的-->finish。

3.完成,刷新父工程;如有多個子工程,繼續按照第二步驟創建。

這時打開XXX中的pom.xml可以看到其中有以下標籤

<modules>

  <module>xxx1</module>

</modules>

選擇編譯XXX時,會依次對它的所有Module執行相同操作。

 

常用Maven插件

maven-antrun-plugin

http://maven.apache.org/plugins/maven-antrun-plugin/

maven-antrun-plugin能讓用戶在Maven項目中運行Ant任務。用戶可以直接在該插件的配置以Ant的方式編寫Target,然後交給該插件的run目標去執行。在一些由Ant往Maven遷移的項目中,該插件尤其有用。此外當你發現需要編寫一些自定義程度很高的任務,同時又覺得Maven不夠靈活時,也可以以Ant的方式實現之。maven-antrun-plugin的run目標通常與生命週期綁定運行。

 

maven-archetype-plugin

http://maven.apache.org/archetype/maven-archetype-plugin/

Archtype指項目的骨架,Maven初學者最開始執行的Maven命令可能就是mvn archetype:generate,這實際上就是讓maven-archetype-plugin生成一個很簡單的項目骨架,幫助開發者快速上手。可能也有人看到一些文檔寫了mvn archetype:create,但實際上create目標已經被棄用了,取而代之的是generate目標,該目標使用交互式的方式提示用戶輸入必要的信息以創建項目,體驗更好。 maven-archetype-plugin還有一些其他目標幫助用戶自己定義項目原型,例如你由一個產品需要交付給很多客戶進行二次開發,你就可以爲他們提供一個Archtype,幫助他們快速上手。

 

maven-assembly-plugin

http://maven.apache.org/plugins/maven-assembly-plugin/

maven-assembly-plugin的用途是製作項目分發包,該分發包可能包含了項目的可執行文件、源代碼、readme、平臺腳本等等。 maven-assembly-plugin支持各種主流的格式如zip、tar.gz、jar和war等,具體打包哪些文件是高度可控的,例如用戶可以按文件級別的粒度、文件集級別的粒度、模塊級別的粒度、以及依賴級別的粒度控制打包,此外,包含和排除配置也是支持的。maven-assembly- plugin要求用戶使用一個名爲assembly.xml的元數據文件來表述打包,它的single目標可以直接在命令行調用,也可以被綁定至生命週期。

 

maven-dependency-plugin

http://maven.apache.org/plugins/maven-dependency-plugin/

maven-dependency-plugin最大的用途是幫助分析項目依賴,dependency:list能夠列出項目最終解析到的依賴列表,dependency:tree能進一步的描繪項目依賴樹,dependency:analyze可以告訴你項目依賴潛在的問題,如果你有直接使用到的卻未聲明的依賴,該目標就會發出警告。maven-dependency-plugin還有很多目標幫助你操作依賴文件,例如dependency:copy-dependencies能將項目依賴從本地Maven倉庫複製到某個特定的文件夾下面。

 

maven-enforcer-plugin

http://maven.apache.org/plugins/maven-enforcer-plugin/

在一個稍大一點的組織或團隊中,你無法保證所有成員都熟悉Maven,那他們做一些比較愚蠢的事情就會變得很正常,例如給項目引入了外部的SNAPSHOT依賴而導致構建不穩定,使用了一個與大家不一致的Maven版本而經常抱怨構建出現詭異問題。maven-enforcer- plugin能夠幫助你避免之類問題,它允許你創建一系列規則強制大家遵守,包括設定Java版本、設定Maven版本、禁止某些依賴、禁止 SNAPSHOT依賴。只要在一個父POM配置規則,然後讓大家繼承,當規則遭到破壞的時候,Maven就會報錯。除了標準的規則之外,你還可以擴展該插件,編寫自己的規則。maven-enforcer-plugin的enforce目標負責檢查規則,它默認綁定到生命週期的validate階段。

 

maven-help-plugin

http://maven.apache.org/plugins/maven-help-plugin/

maven-help-plugin是一個小巧的輔助工具,最簡單的help:system可以打印所有可用的環境變量和Java系統屬性。help:effective-pomhelp:effective-settings最爲有用,它們分別打印項目的有效POM和有效settings,有效POM是指合併了所有父POM(包括Super POM)後的XML,當你不確定POM的某些信息從何而來時,就可以查看有效POM。有效settings同理,特別是當你發現自己配置的 settings.xml沒有生效時,就可以用help:effective-settings來驗證。此外,maven-help-plugin的describe目標可以幫助你描述任何一個Maven插件的信息,還有all-profiles目標和active-profiles目標幫助查看項目的Profile。

 

maven-release-plugin

http://maven.apache.org/plugins/maven-release-plugin/

maven-release-plugin的用途是幫助自動化項目版本發佈,它依賴於POM中的SCM信息。release:prepare用來準備版本發佈,具體的工作包括檢查是否有未提交代碼、檢查是否有SNAPSHOT依賴、升級項目的SNAPSHOT版本至RELEASE版本、爲項目打標籤等等。release:perform則是簽出標籤中的RELEASE源碼,構建併發布。版本發佈是非常瑣碎的工作,它涉及了各種檢查,而且由於該工作僅僅是偶爾需要,因此手動操作很容易遺漏一些細節,maven-release-plugin讓該工作變得非常快速簡便,不易出錯。maven-release-plugin的各種目標通常直接在命令行調用,因爲版本發佈顯然不是日常構建生命週期的一部分。

 

maven-resources-plugin

http://maven.apache.org/plugins/maven-resources-plugin/

爲了使項目結構更爲清晰,Maven區別對待Java代碼文件和資源文件,maven-compiler-plugin用來編譯Java代碼,maven-resources-plugin則用來處理資源文件。默認的主資源文件目錄是src/main/resources,很多用戶會需要添加額外的資源文件目錄,這個時候就可以通過配置maven-resources-plugin來實現。此外,資源文件過濾也是Maven的一大特性,你可以在資源文件中使用${propertyName}形式的Maven屬性,然後配置maven-resources-plugin開啓對資源文件的過濾,之後就可以針對不同環境通過命令行或者Profile傳入屬性的值,以實現更爲靈活的構建。

 

maven-surefire-plugin

http://maven.apache.org/plugins/maven-surefire-plugin/

可能是由於歷史的原因,Maven 2/3中用於執行測試的插件不是maven-test-plugin,而是maven-surefire-plugin。其實大部分時間內,只要你的測試類遵循通用的命令約定(以Test結尾、以TestCase結尾、或者以Test開頭),就幾乎不用知曉該插件的存在。然而在當你想要跳過測試、排除某些測試類、或者使用一些TestNG特性的時候,瞭解maven-surefire-plugin的一些配置選項就很有用了。例如 mvn test -Dtest=FooTest 這樣一條命令的效果是僅運行FooTest測試類,這是通過控制maven-surefire-plugin的test參數實現的。

 

build-helper-maven-plugin

http://mojo.codehaus.org/build-helper-maven-plugin/

Maven默認只允許指定一個主Java代碼目錄和一個測試Java代碼目錄,雖然這其實是個應當儘量遵守的約定,但偶爾你還是會希望能夠指定多個源碼目錄(例如爲了應對遺留項目),build-helper-maven-plugin的add-source目標就是服務於這個目的,通常它被綁定到默認生命週期的generate-sources階段以添加額外的源碼目錄。需要強調的是,這種做法還是不推薦的,因爲它破壞了 Maven的約定,而且可能會遇到其他嚴格遵守約定的插件工具無法正確識別額外的源碼目錄。

build-helper-maven-plugin的另一個非常有用的目標是attach-artifact,使用該目標你可以以classifier的形式選取部分項目文件生成附屬構件,並同時install到本地倉庫,也可以deploy到遠程倉庫。

 

exec-maven-plugin

http://mojo.codehaus.org/exec-maven-plugin/

exec-maven-plugin很好理解,顧名思義,它能讓你運行任何本地的系統程序,在某些特定情況下,運行一個Maven外部的程序可能就是最簡單的問題解決方案,這就是exec:exec的用途,當然,該插件還允許你配置相關的程序運行參數。除了exec目標之外,exec-maven-plugin還提供了一個java目標,該目標要求你提供一個mainClass參數,然後它能夠利用當前項目的依賴作爲classpath,在同一個JVM中運行該mainClass。有時候,爲了簡單的演示一個命令行Java程序,你可以在POM中配置好exec-maven-plugin的相關運行參數,然後直接在命令運行mvn exec:java 以查看運行效果。

 

jetty-maven-plugin

http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin

在進行Web開發的時候,打開瀏覽器對應用進行手動的測試幾乎是無法避免的,這種測試方法通常就是將項目打包成war文件,然後部署到Web容器中,再啓動容器進行驗證,這顯然十分耗時。爲了幫助開發者節省時間,jetty-maven-plugin應運而生,它完全兼容 Maven項目的目錄結構,能夠週期性地檢查源文件,一旦發現變更後自動更新到內置的Jetty Web容器中。做一些基本配置後(例如Web應用的contextPath和自動掃描變更的時間間隔),你只要執行 mvn jetty:run ,然後在IDE中修改代碼,代碼經IDE自動編譯後產生變更,再由jetty-maven-plugin偵測到後更新至Jetty容器,這時你就可以直接測試Web頁面了。需要注意的是,jetty-maven-plugin並不是宿主於Apache或Codehaus的官方插件,因此使用的時候需要額外的配置settings.xml的pluginGroups元素,將org.mortbay.jetty這個pluginGroup加入。

 

versions-maven-plugin

http://mojo.codehaus.org/versions-maven-plugin/

很多Maven用戶遇到過這樣一個問題,當項目包含大量模塊的時候,爲他們集體更新版本就變成一件煩人的事情,到底有沒有自動化工具能幫助完成這件事情呢?(當然你可以使用sed之類的文本操作工具,不過不在本文討論範圍)答案是肯定的,versions-maven- plugin提供了很多目標幫助你管理Maven項目的各種版本信息。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能幫助你把所有模塊的版本更新到1.1-SNAPSHOT。該插件還提供了其他一些很有用的目標,display-dependency- updates能告訴你項目依賴有哪些可用的更新;類似的display-plugin-updates能告訴你可用的插件更新;然後use- latest-versions能自動幫你將所有依賴升級到最新版本。最後,如果你對所做的更改滿意,則可以使用 mvn versions:commit 提交,不滿意的話也可以使用 mvn versions:revert 進行撤銷。

 

更多詳情請參考https://maven.apache.org/plugins/

 

常用Maven命令

生命週期

階段描述

mvn validate

驗證項目是否正確,以及所有爲了完整構建必要的信息是否可用

mvn generate-sources

生成所有需要包含在編譯過程中的源代碼

mvn process-sources

處理源代碼,比如過濾一些值

mvn generate-resources

生成所有需要包含在打包過程中的資源文件

mvn process-resources

複製並處理資源文件至目標目錄,準備打包

mvn compile

編譯項目的源代碼

mvn process-classes

後處理編譯生成的文件,例如對Java類進行字節碼增強(bytecode enhancement)

mvn generate-test-sources

生成所有包含在測試編譯過程中的測試源碼

mvn process-test-sources

處理測試源碼,比如過濾一些值

mvn generate-test-resources

生成測試需要的資源文件

mvn process-test-resources

複製並處理測試資源文件至測試目標目錄

mvn test-compile

編譯測試源碼至測試目標目錄

mvn test

使用合適的單元測試框架運行測試。這些測試應該不需要代碼被打包或發佈

mvn prepare-package

在真正的打包之前,執行一些準備打包必要的操作。這通常會產生一個包的展開的處理過的版本(將會在Maven 2.1+中實現)

mvn package

將編譯好的代碼打包成可分發的格式,如JAR,WAR,或者EAR

mvn pre-integration-test

執行一些在集成測試運行之前需要的動作。如建立集成測試需要的環境

mvn integration-test

如果有必要的話,處理包併發布至集成測試可以運行的環境

mvn post-integration-test

執行一些在集成測試運行之後需要的動作。如清理集成測試環境。

mvn verify

執行所有檢查,驗證包是有效的,符合質量規範

mvn install

安裝包至本地倉庫,以備本地的其它項目作爲依賴使用

mvn deploy

複製最終的包至遠程倉庫,共享給其它開發人員和項目(通常和一次正式的發佈相關)

使用參數

-Dmaven.test.skip=true: 跳過單元測試(eg: mcn clean package -Dmaven.test.skip=true)

 

常見問題

dependencies和dependencyManagement,plugins和

pluginManagement

有什麼區別?

dependencyManagement是表示依賴jar包的聲明,即你在項目中的dependencyManagement下聲明瞭依賴,maven不會加載該依賴,dependencyManagement聲明可以被繼承。

dependencyManagement的一個使用案例是當有父子項目的時候,父項目中可以利用dependencyManagement聲明子項目中需要用到的依賴jar包,之後,當某個或者某幾個子項目需要加載該插件的時候,就可以在子項目中dependencies節點只配置 groupId 和 artifactId就可以完成插件的引用。

dependencyManagement主要是爲了統一管理插件,確保所有子項目使用的插件版本保持一致,類似的還是plugins和pluginManagement。

 

更多閱讀

maven 在線筆記: https://atlantis1024.gitbooks.io/maven-notes/content/

參考資料

https://maven.apache.org/index.html ——官方文檔地址

http://www.oschina.net/question/158170_29368

http://www.cnblogs.com/crazy-fox/archive/2012/02/09/2343722.html

作者:靜默虛空
歡迎任何形式的轉載,但請務必註明出處。
限於本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。

分類: javaee
43
3
關注  |  頂部  |  評論
« 上一篇:認識Java Core和Heap Dump
» 下一篇:[Quartz筆記]玩轉定時調度
posted @ 2016-06-16 16:18 靜默虛空 閱讀(11671) 評論(4編輯 收藏

評論列表
  
#1樓 2017-01-09 09:16 快樂的灰太狼  
樓主,我在安裝m2e插件之後,重啓eclipse總是彈出警告,警告框的內容大致是當前eclipse運行在jre環境,必須配置jdk,然後我按照網上的方式打開eclipse.ini添加-vm d:\jdk1.8\bin\javaw還是無效,你有沒有遇到這種問題啊
  
#2樓[樓主] 2017-01-13 16:16 靜默虛空  
@ 快樂的灰太狼
沒有遇到過
  
#3樓 2017-03-30 16:51 yunxiong  
mark and thanks.
  
#4樓 2017-09-30 11:03 zacader  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章