2017年6月20日 星期二

[ Maven ] Maven 教學 (Part1)

Source From Here 
前言 
Ant build.xml,雖然有過去建立的範本,但是還是的根據不同狀況加以 改寫 (比如不同的打包方式,如同時 deploy 到 tomcat 與 jboss 時用到不 同的 log4J 設定,或是像 GWT 必須加上一道 Comple 手續);當有新版本的 Liberary出來的時候,還得忙著下載新 Jar,然後發現不相容時,還得改回來… Maven 最大的好處,就是把上面的無聊事標準化,簡單化了,用久了,還真得 少不了它。 

建立 Maven 環境 
在命令視窗執行 mvn archetype:generate 命令,使用互動方式建立 Project, 會依序問幾個問題: 
# mvn archetype:generate
...
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 990: 
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
Choose a number: 6:
  // 選擇範本的版本,會列出一些範本可用的版本,其差異是就不用版本的範本可能會建立有不同的資源檔
Define value for property 'groupId': john.test // 輸入要建立 Project 所隸屬的組織或公司,如我自已用 john.test
Define value for property 'artifactId': Maventest // 就是 Project 名稱,例如 Maventest
Define value for property 'version' 1.0-SNAPSHOT: : 
Define value for property 'package' john.test: : 
Confirm properties configuration:
groupId: john.test
artifactId: Maventest
version: 1.0-SNAPSHOT
package: john.test
Y: :
 Y

# ls -hl
total 0
drwxr-xr-x 3 root root 30 Jun 21 12:26 Maventest

# ls -hl Maventest/
total 4.0K
-rw-r--r-- 1 root root 749 Jun 21 12:26 pom.xml
drwxr-xr-x 4 root root 28 Jun 21 12:26 src

確定後建立 Project 的基本架構,如果您不要用互動的方式,上述動作可以以下指令完成相同的事 
# mvn archetype:create -DgroupId=john.test -DartifactId=Maventest \
-DpackageName=john.test -DarchetypeArtifactId:maven-archetype-quickstart \
-Dversion=1.0-SNAPSHOT

Maven 的識別管理 
Maven的識別管理,分為三層 groupId:artifactId:version,一個組織 (group) 可能存在多個 Project (atrifact),每個 Project 也可能存在多個版本 (version), 整個函式庫就以這種檔檔案架構進行處理,當使用的函式不存在時,Maven 會到 http://repo1.maven.org/maven2/ 或是 http://repo2.maven.org/maven2/ 進行下載,下載後存到您電腦上的函式庫. 

Maven 的 Project 管理 
Maven 的管理設定主要靠 pom.xml 進行,打開剛才建立的 Project 設定檔,內容說明如下: 
- Maventest/pom.xml 

首先要說明的是 dependencies 段落,比如說,Project 內會用到 commons-loggin 的 Library,我們可以在此加入新的 dependency 段落, 

不知道 commons-loggin 的識別資料? 沒關係,到 這裡 查。至於 scope 可以不填,表示打包 Project (如 war,ear…) 時, 引用的 Library 會一起被打包,Scope 的值說明如下 (更多請參考 Introduction to the Dependency Mechanism): 


至於 commons-logging 是否須要使用到其它的Library,根本完全不用在意,因為 Maven 會自動導入相關的 Library. 

Project 目錄架構 
以建立 web 程式來說,其目錄架構說明如下: 


Maven 引用第三方函式庫 
之前有說過,Maven 有專門存放函式的 repository (檔案庫), 但是 ASF 再厲害,也不可能搜羅所有Library,所以必要的時候,我們必須引用第三方的函式檔案庫, 以下為可能會用到的來源(加入到 pom.xml): 


  Maven Plugin 

一開始的時候,我們執行 "mvn archetype:generate" 建立 Project,mvn 後面接的指令 叫 goal 由 "前置字:識別字" 表示要執行的作業。這些執業作業 (命令) 是由所謂的 plugin 所提供,plugin 是一種專供 Maven 本身使用的 Library,同一個 plugin 通常使用同一前置字,然後本身會帶有說明提供那些作業的自我解說檔 (metadata), 通常這個自我解說檔,也會定義每種作業隸屬於那種 phase (作業階段);Maven 本身早已知道許許多多的 goal 的定義,當 Maven 執行特定的 goal 時,缺少的 Plugin,Maven 就會自動去 Repository 下載相關的檔案。 

Maven 的指令可以串接,例如以下指令: 
# mvn clean package javadoc:javadoc exec:exec

表示,先刪除 target 目錄後再行打包 Project,然後產生文件,再執行專案(需要額外設定)。 

上述的 clean、package (打包)都很容易理解,可是為何又出現了 javadoc:javadocexec:exec 這樣的表示, 這是因為 Plugin 是 Maven 裡面的一種特殊專案,她裡面存在一些 task,當這些 Plugin 被包含進專案的 pom.xml 時, 例如要執行 maven-javadoc-plugin 這個 Plugin 的 javadoc task 時,完整的命令下法應該是: 
# mvn org.apache.maven.plugins:maven-javadoc-plugin:2.10.1:javadoc

但是因為在的 Jar 的 Metadata 中已經標注了它的 prefix,在 Maven 執行時,會去讀取每個 plugin java 的 metadata, 而 maven-javadoc-plugin 的 metadata 標記為 javadoc,所以才省略為 javadoc:javadoc,至於前面的 clean package 等則是 maven lifecycle 的一部分 (參考 Introduction to the Build Lifecycle),會綁定特定的 Plugin,然後執行 該 Plugin 的 task。 

plugin 的定義結構通常如下 : 


Project變數 

我們建立的第一個 Project 的 pom.xml 檔案內有一個段落,可以讓我們定義一些變數, 例如Spring 通常含有多種 Library,其引用版本應該一致,所以我通常會定義一個變數: 
  然後,定義版本別的地方會寫成 
  1. ${org.springframework.version}  
以後當版本變更的時候,只要修改 下的 4.2.0.RELEASE,就可以引用新的版本。 初建立時的 pom.xml 內已經有一個變數: 
  為什麼沒有看到在那裡引用呢? 其實,前面已經提過,Maven 的所有作業都是靠許多的 Plugin 來達成,雖然在這個 pom.xml 內沒有看到引用任何 Plugin, 但當我們執行 "mvn compile"的時候,因為 Maven 已經內定很多指令所使用的 Plugin,所以實際上該命令會去執行: 
mvn compiler:compile

而 compiler Plugin,encoding 會預設參考 ${project.build.sourceEncoding} 這個變數, 所以我們在 pom.xml 的指定這個變數的值為"UTF-8",所以在編譯程式時,編譯器就會知道程式使用的編碼。 這邊有列出一些預設的變數,可以參考使用。 最後一提的是 build 內可放一個 finalName,一般來說打包的最後檔名為 artifactId-version.war (jar,ear),一般來說,web 檔deploy 時總希望固定一個名字,使用 finalName 與一些變數就可以將打包檔的名稱固定住, 例如,我們打包的名字不要有版本資料便可設定如下: 
  1. ${project.artifact}.war  
以下是一些預設變數的列表: 

Maven phrase 
之前說過 goal 可是設定屬於某個 phase,而 phase 則可組成 lifecycle (生命週期),在 Maven 有三個 LifeCycle,分別是 clean 、 default 與 site , clean 周期負責 Project 的清理,default 周期負責 Project 的建置而 site 周期則是負責產生 Project 的文檔。 例如執行 "mvn package" 時,因為它是屬於 defulat 這個 life cycle,所以從 phase validate 到 package 的所有相關的 Goals 都會被執行. 

例如 "mvn package" 這個 Goals,由 內定的 Goal 可以知道, 它可能會執行 Goal "mvn jar:jar" 、 "mvn ejb:ejb" 或是 "mvn ejb3:ejb3" (端看您的專案引用了那些Plugin,預設是 "jar:jar"), 而 "package" 這個 Goal 是屬於 "default" 這個 Phase,所以如 ... "compile"..."test"這些 Phase 下的 Goal (如 compile、test-compile、test...) 會先被執行完成後, 才會輪到 "package" 這個Goal,一旦之前某個 goals 執行失敗就會停止,必須等到所有的 goals 都沒有問題才可完成打包作業。 

以下列舉一些常用的指令 (goals): 

Supplement 
How To Install Apache Maven on CentOS/RHEL 7/6/5 
Eclipse + Maven 2 開發 Java SE 專案 - 1

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...