用了一段時間的maven,可是隻是簡單的使用它來解決依賴問題以及打包而已,配置文件只是使用了<dependency>
這麼一個配置。最近好好接觸了一下maven的生命週期和插件機制,被其強大的可配置性所折服。此處簡要記錄本身所感並分享。html
maven中全部的插件都是配置在標籤<build>
--><plugins>
下面,其下每個<plugin>
標籤對應一個插件。官方自帶的插件五花八門,用的最多的無非是maven-compiler-plugin
、maven-dependency-plugin
、maven-surefire-plugin
等。官方網址
每個插件能夠定義插件的groupId
與artifactId
,以及要執行的<executions>
。executions
下能夠定義一大堆的execution
用來定義具體的任務,其中又包括目標、綁定的階段、配置等參數。大體上配置文件以下:apache
xml<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <executions> <execution> <id>compile</id> <goals> <goal>compile</goal> </goals> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.10</version> <executions> <execution> <id>get_source</id> <goals> <goal>get</goal> <goal>unpack</goal> </goals> <phase>process-resources</phase> <configuration> <artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact> <artifactItems> <artifactItem> <groupId>com.alibaba.middleware.race</groupId> <artifactId>rpc-api</artifactId> <version>1.0</version> <classifier>sources</classifier> </artifactItem> </artifactItems> <outputDirectory>${project.build.sourceDirectory}</outputDirectory> <excludes>META-INF\/**</excludes> </configuration> </execution> </executions> <!--<configuration>--> <!--<artifact>com.alibaba.middleware.race:rpc-api:1.0:jar:sources</artifact>--> <!--</configuration>--> </plugin> </plugins> </build>
其中maven-dependency-plugin
插件下的任務先從中央庫下載com.alibaba.middleware.race:rpc-api:1.0:jar:sources
的jar包,再解壓到指定的目錄並排除META-INF
文件夾。(因爲本人剛接觸,這種寫法可能不是最佳實踐,若是有人有更好的寫法的話懇請告知。)這個id爲get_source
的任務綁定到了階段process-resources
,在執行到default
生命週期的該階段時會執行這個任務。運行mvn compile
,成功執行,感受良好。api
如今想要在命令行下不是執行某個階段,而是直接執行某個插件的任務。命令maven
mvn org.apache.maven.plugins:maven-dependency-plugin:get -Dartifact=com.alibaba.middleware.race:rpc-api:1.0:jar:sources
或者其縮寫學習
mvn dependency:get -Dartifact=com.alibaba.middleware.race:rpc-api:1.0:jar:sources
成功下載了指定的源文件。看來命令行執行插件也很容易,可是有一個小問題:我沒辦法不指定artifact
,也就是直接執行ui
mvn dependency:get
會有錯誤。可是我想使用配置文件中的artifact配置,而不想每次運行都敲那麼一大串(不使用週期綁定的狀況下)。插件
我嘗試了在上面的配置文件中加入了註釋掉的那部份內容,直接運行mvn dependency:get
,沒出錯,彷佛可行。命令行
註釋部分的內容雖然可行,dependency
插件的get
任務雖然找到了該配置,可是缺點也很明顯:code
對於1,假如如今我有另外一個id爲get_sources2
的任務,它是把com.alibaba.middleware.race:rpcapi:2.0:jar:sources
這麼一個版本的包下載並拷貝到相同目錄下,並且和get_sources
只能運行一個。這樣的話明顯的不能使用「全局的配置」,這樣會有衝突;而在每一個execution
中定義的參數,是沒辦法被mvn dependency:get
這樣識別的。xml
對於2,我要想執行「下載並解壓到指定目錄」這個操做,必須執行:
mvn dependency:get mvn dependency:unpack ##(固然,須要先向get那樣配置參數)
兩條語句雖然很少,可是當任務中又有copy
等其餘goal
時,也是至關麻煩的。
最爲理想的狀態是:有這麼一條命令,可以讓我指定運行時的某個插件具體的任務,而不是僅僅運行某個目標。好比相似以下的命令:
mvn dependency:get_sources ##(get_sources爲某個execution的id)
這樣的話,這兩個問題都完美解決了(不綁定生命週期的階段狀況下)。可是很遺憾,maven不支持這種操做。
不過卻是有一種辦法能夠解決問題1:使用默認的execution id
名:default-cli
。凡是execution id
爲default-cli
的任務,命令行運行時若是goal
在goals
中有定義,則goal與其參數會被執行。這實際上是將「全局配置」放在了「默認配置」中。好處在於能夠定義幾個任務,而後須要執行哪一個任務,只須要把<id>
改成default-cli
就好了。雖然要修改pom.xml
,可是也不算麻煩。
對於問題2,若是存在任務之間的依賴定義的話,卻是能夠把目標get
和unpack
分別定義在不一樣的任務中,而後任務中指定依賴關係:unpack
依賴get
,這樣只須要執行unpack
便可自動執行get
,就像ant中<target>
的depends
那樣。可是我沒有找到如何定義這種「任務間的依賴」。
固然,並不是沒有可能簡化:若是能本身寫一個插件的話,一切問題都不在話下。可是如今本身的水平還遠遠沒有到那種程度。學習之路依舊遙遠。
PS:Maven相比於ant的很大的進步之處在於其週期和階段的概念。除了極少數不適合綁定階段的任務外仍是多使用階段和任務的綁定比較好,能省不少麻煩。
PPS:本人學習maven未深,理解可能出現誤差,若是有人發現文中的疏漏或者錯誤,懇請指正以避免誤導他人。