[maven] 經常使用插件解析
參考資料:http://my.oschina.net/zh119893/blog/276090 html
咱們都知道Maven本質上是一個插件框架,它的核心並不執行任何具體的構建任務,全部這些任務都交給插件來完成。java
例如編譯源代碼是由maven-compiler-plugin完成的。web
進一步說,每一個任務對應了一個插件目標(goal),每一個插件會有一個或者多個目標。apache
例如maven-compiler-plugin的compile目標用來編譯位於src/main/java/
目錄下的主源碼,testCompile目標用來編譯位於src/test/java/
目錄下的測試源碼。瀏覽器
用戶能夠經過兩種方式調用Maven插件目標。tomcat
第一種方式是將插件目標與生命週期階段(lifecycle phase)綁定,這樣用戶在命令行只是輸入生命週期階段而已。服務器
例如Maven默認將maven-compiler-plugin的compile目標與compile生命週期階段綁定,所以命令mvn compile其實是先定位到compile這一輩子命週期階段,而後再根據綁定關係調用maven-compiler-plugin的compile目標。併發
第二種方式是直接在命令行指定要執行的插件目標。app
例如mvn archetype:generate 就表示調用maven-archetype-plugin的generate目標,這種帶冒號的調用方式與生命週期無關。框架
認識上述Maven插件的基本概念能幫助你理解Maven的工做機制,不過要想更高效率地使用Maven,瞭解一些經常使用的插件仍是頗有必要的,這能夠幫助你避免一不當心從新發明輪子。
多年來Maven社區積累了大量的經驗,並隨之造成了一個成熟的插件生態圈。
Maven官方有兩個插件列表:
第一個列表的GroupId爲org.apache.maven.plugins,這裏的插件最爲成熟,具體地址爲:http://maven.apache.org/plugins/index.html。
第二個列表的GroupId爲org.codehaus.mojo,這裏的插件沒有那麼核心,但也有很多十分有用,其地址爲:http://mojo.codehaus.org/plugins.html。
接下來介紹一些經常使用的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-pom和help: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 進行撤銷。
小結
本文介紹了一些最經常使用的Maven插件,這裏指的「經常使用」是指常常須要進行配置的插件,事實上咱們用Maven的時候不少其它插件也是必須的,
例如默認的編譯插件maven-compiler-plugin和默認的打包插件maven-jar-plugin,但由於不多須要對它們進行配置,所以不在本文討論範圍。
瞭解經常使用的Maven插件能幫助你事倍功半地完成項目構建任務,反之你就可能會由於常常遇到一些難以解決的問題而感到沮喪。
本文介紹的插件基本能覆蓋大部分Maven用戶的平常使用須要,若是你真有很是特殊的需求,自行編寫一個Maven插件也不是難事,更況且還有這麼多開放源代碼的插件供你參考。
一些常見例子
① maven-jetty-plugin
http://blog.sina.com.cn/s/blog_62b0363101012he0.html
http://stamen.iteye.com/blog/1933452
輸入:mvn jetty:run。這將在端口爲8080的Jetty服務器上啓動你的項目。Jetty將持續運行,直到插件是明確中止。例如,按下<ctrl-c>,或使用mvn jetty:stop命令。
<build> <finalName>rop-sample</finalName> <plugins> <!-- jetty插件 --> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.5</version> <configuration> <webAppSourceDirectory>src/main/webapp</webAppSourceDirectory> <scanIntervalSeconds>3</scanIntervalSeconds> <contextPath>/</contextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>8088</port> </connector> </connectors> </configuration> </plugin> </plugins> </build>
② maven-compiler-plugin 編譯源代碼
在Maven項目下,咱們須要配置"maven-compiler-plugin"的"encoding"參數
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <encoding>UTF8</encoding> </configuration> </plugin> </plugins>
須要在編譯和生成的時候使用不一樣的jdk版本
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.6</source> <target>1.7</target> </configuration> </plugin>
③ maven-war-plugin
打包war項目的時候排除某些web資源文件,這時就應該配置maven-war-plugin以下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <webResources> <resource> <directory>src/main/webapp</directory> <excludes> <exclude>**/*.jpg</exclude> </excludes> </resource> </webResources> </configuration> </plugin>
④ maven-source-plugin 生成源碼包
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.1.2</version> <executions> <execution> <id>attach-sources</id> <phase>verify</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin>
<!-- 源代碼打包插件 -->
<plugin> <artifactId>maven-source-plugin</artifactId> <version>2.1</version> <configuration> <!-- <finalName>${project.build.name}</finalName> --> <attach>true</attach> <encoding>${project.build.sourceEncoding}</encoding> </configuration> <executions> <execution> <phase>compile</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin>
⑤ maven-javadoc-plugin 生成javadoc包
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>2.7</version> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin>
⑥ maven-assembly-plugin
它支持各類打包文件格式,包括zip、tar.gz、tar.bz2等等,經過一個打包描述文件(該例中是src/main/assembly.xml),它可以幫助用戶選擇具體打包哪些文件集合、依賴、模塊、和甚至本地倉庫文件,每一個項的具體打包路徑用戶也能自由控制。以下就是對應上述需求的打包描述文件src/main/assembly.xml:
<assembly> <id>bin</id> <formats> <format>zip</format> </formats> <dependencySets> <dependencySet> <useProjectArtifact>true</useProjectArtifact> <outputDirectory>lib</outputDirectory> </dependencySet> </dependencySets> <fileSets> <fileSet> <outputDirectory>/</outputDirectory> <includes> <include>README.txt</include> </includes> </fileSet> <fileSet> <directory>src/main/scripts</directory> <outputDirectory>/bin</outputDirectory> <includes> <include>run.sh</include> <include>run.bat</include> </includes> </fileSet> </fileSets> </assembly>
最終生成一個zip格式的分發包,它包含以下的一個結構: bin/ lib/ README.txt
最後,咱們須要配置maven-assembly-plugin使用打包描述文件,並綁定生命週期階段使其自動執行打包操做:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2.1</version> <configuration> <descriptors> <descriptor>src/main/assembly/assembly.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
運行mvn clean package以後,咱們就能在target/目錄下獲得名爲hello-world-1.0-bin.zip的分發包了。
⑦ maven-surefire-plugin 打包時跳過單元測試
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.6</version> <configuration> <skip>true</skip> </configuration> </plugin>
mvn package -Dmaven.test.skip=true
若是單元測試中有輸出中文,eclipse的控制檯裏中文可能會變成亂碼輸出,也能夠經過這個插件解決,參考配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <configuration> <forkMode>once</forkMode> <argLine>-Dfile.encoding=UTF-8</argLine> </plugin>
⑧ maven-resource-plugin
<!-- 設置資源文件的編碼方式 -->
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>compile</phase> </execution> </executions> <configuration> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin>
把web項目的輸出copy到tomcat的webapp下
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.5</version> <executions> <execution> <id>deploy-website</id> <phase>package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${server_home}/webapps/${project.build.finalName}</outputDirectory> <resources> <resource> <directory>${project.build.directory}/${project.build.finalName}</directory> </resource> </resources> </configuration> </execution> </executions> </plugin>
⑨ maven-dependency-plugin
自動拷貝jar包到target目錄
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>copy-dependencies</id> <phase>compile</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <!-- ${project.build.directory}爲Maven內置變量,缺省爲target --> <outputDirectory>${project.build.directory}/lib</outputDirectory> <!-- 表示是否不包含間接依賴的包 --> <excludeTransitive>false</excludeTransitive> <!-- 表示複製的jar文件去掉版本信息 --> <stripVersion>true</stripVersion> </configuration> </execution> </executions> </plugin>
在部署war包時,須要將項目依賴的jar包,也打到war包中,所以就會用到上述插件
⑩ 在打包時,須要清空一些指定的目錄
在一個J2EE項目中,想使用mvn clean命令清除target裏的內容的同時,也清除tomcat/webapp下的相應目錄,該怎麼辦呢?
<plugin> <artifactId>maven-clean-plugin</artifactId> <configuration> <verbose>true</verbose> <filesets> <fileset> <directory>c:/a/b/c/</directory> </fileset> </filesets> </configuration> </plugin>
本例中,刪除的是c:/a/b/c/目錄.
當用戶在該maven項目中執行mvn clean後,除了刪除clean插件默認的
project.build.directory
project.build.outputDirectory
project.build.testOutputDirectory
project.reporting.outputDirectory
c:/a/b/c/
十一、利用tomcat-maven-plugin插件將項目自動打包並部署到tomcat中
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <configuration> <server>tomcat6-manager</server> <path>/${project.build.name}</path> <url>http://localhost:8080/manager</url> <username>admin</username> <password>admin</password> </configuration> <executions> <execution> <phase>deploy</phase> <goals> <goal>deploy</goal> </goals> </execution> </executions> </plugin> </plugins>
path: 是指項目部署到tomcat後的項目名稱
url: 是指tomcat的manager訪問地址
server: 這個是tomcat服務名稱設置,須要配置maven的settings.xml文件,在servers節點中手動配置server,以下所示:
<server> <id>tomcat6-manager</id> <username>admin</username> <password>admin</password> </server>
十二、利用cargo-maven2-plugin插件將項目自動打包並部署到tomcat中
cargo插件能夠幫助你完成WAR包到服務器的部署及服務器的啓動和關閉等工做,方便,快速!
<plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.2.0</version> <configuration> <container> <containerId>${server_name}</containerId> <home>${server_home}</home> </container> <configuration> <type>existing</type> <home>${server_home}</home> <properties> <cargo.servlet.port>8088</cargo.servlet.port> </properties> </configuration> </configuration> </plugin>
注意,若是你的tomcat服務器的端口使用的不是默認的8080(如本例中的8088),則須要使用cargo.servlet.port參數將cargo的監聽端口也配置到tomcat的那個監聽端口(如本例中的8088),不然使用mvn cargo:run啓動的服務器會在120000毫秒(120秒)後自動關閉!
mvn cargo:start命令完成WAR包部署後,啓動服務器,而後會將服務器當即關掉;
mvn cargo:run命令完成WAR包部署後,啓動服務器,直到你Ctrl+C將服務器關掉;
mvn cargo:stop命令關閉服務器。
參考:http://cargo.codehaus.org/Maven2+plugin
<plugin> <!-- 指定插件名稱及版本號 --> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.2.3</version> <!-- 插件的Tomcat6.x配置 --> <configuration> <!-- 容器的配置 --> <container> <!-- 指定服務器版本 --> <containerId>tomcat6x</containerId> <!-- 指定服務器的安裝目錄 --> <home>E:\Program Files\tomcat-6.0.32</home> </container> <!-- 具體的配置 --> <configuration> <!-- 部署模式:existing、standalone等 --> <type>existing</type> <!-- Tomcat的位置,即catalina.home --> <home>E:\Program Files\tomcat-6.0.32</home> <!-- 配置屬性 --> <properties> <!-- 管理地址 --> <cargo.tomcat.manager.url>http://localhost:8080/manager</cargo.tomcat.manager.url> <!-- Tomcat用戶名 --> <cargo.remote.username>admin</cargo.remote.username> <!-- Tomcat密碼 --> <cargo.remote.password>admin</cargo.remote.password> <!-- <cargo.jvmargs> -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8787 </cargo.jvmargs> --> </properties> </configuration> </configuration> </plugin>