maven生命週期和外掛詳解
生命週期和外掛是Maven的兩個核心概念,命令列的輸入往往就對應了生命週期,如mvn package就表示執行預設生命週期階段package。Maven的生命週期是抽象的,其實際行為都由外掛來完成。Maven的生命週期是為了對所有的構建過程進行抽象和統一。
Maven擁有三套相互獨立的生命週期,分別為clean、default和site。clean生命週期的目的是清理專案,default生命週期的目的是構建專案,site目的是建立專案站點。
clean:
1. pre-clean 執行一些清理前需要完成的工作。
2. clean 清理上一次構建生成的檔案。
3. post-clean 執行一些清理後需要完成的工作。
default 包含的操作很多,以下列出主要的:
process-sources 處理專案主資原始檔。一般來說,是對src/main/resources目錄的內容進行變數替換等工作後,複製到專案輸出的主classpath目錄中。
compile 編譯專案的主程式碼。一般來說,是編譯src/main/java目錄下的Java檔案至專案輸出的主classpath目錄中。
process-test-sources 處理專案測試資原始檔 src/main/resources。
test-compile 編譯專案的測試程式碼。src/test/java。
test 使用單元測試框架執行測試,測試程式碼不會被打包或部署。
package 接受編譯好的程式碼,打包成可釋出的格式,如jar。
install 將包安裝到Maven本地倉庫,供本地其他Maven專案使用。
deploy 將最終的包複製到遠端倉庫。
site
pre-site
site 生成專案站點文件。
post-site
site-deploy 將生成的專案站點發布到伺服器上。
外掛目標(Plugin Goal):
一個外掛往往能夠完成多個任務。例如maven-dependency-plugin,它能夠基於專案依賴做很多事情,例如分析專案依賴,幫助找出所有已解析的依賴等等,每個功能就是一個外掛目標。用法是 <外掛字首:目標>。例如maven-dependency-plugin有十多個目標,最常用的:
mvn dependency:analyze //執行結果: [WARNING] Used undeclared dependencies found: [WARNING] org.springframework:spring-web:jar:5.0.4.RELEASE:compile [WARNING] org.springframework.boot:spring-boot-autoconfigure:jar:2.0.0.RELEASE:compile [WARNING] org.springframework:spring-tx:jar:5.0.4.RELEASE:compile [WARNING] org.springframework.boot:spring-boot:jar:2.0.0.RELEASE:compile [WARNING] Unused declared dependencies found: [WARNING] com.alibaba:fastjson:jar:1.2.31:compile [WARNING] org.springframework.boot:spring-boot-starter-test:jar:2.0.0.RELEASE:test [WARNING] org.springframework.boot:spring-boot-starter-web:jar:2.0.0.RELEASE:compile [WARNING] org.mybatis.spring.boot:mybatis-spring-boot-starter:jar:1.3.0:compile [WARNING] com.google.guava:guava:jar:23.0:compile
Unused declared dependencies found即聲明瞭沒使用的依賴,通過這個外掛,就能看到專案依賴的情況。如果是因為繼承了父pom檔案而導致無用依賴太多,那麼可以使用dependencyManagement管理。
外掛繫結:
Maven的生命週期與外掛相互繫結,用以完成實際的構建任務。例如專案編譯這一任務,它對應了default生命週期的compile階段,而maven-compile-plugin這一外掛的compile目標能完成該任務。因此,將它們繫結,就能實現編譯的目的。
Maven在核心為一些主要的生命週期階段綁定了很多外掛的目標,當用戶通過命令列呼叫生命週期階段的時候,對於的外掛目標就會執行相應的任務。例如clean繫結mavevn-clean-plugin:clean。
而default生命週期,由於專案的打包型別會影響構建的具體過程,因此,default生命週期的階段與外掛的目標繫結關係由專案打包型別所決定,通過POM中的packaging元素定義。最常用的打包型別是jar。以下是基於jar,default生命週期的內建外掛繫結關係:
default生命週期還有很多其他階段,預設它們沒有繫結任何外掛,因此也沒有實際行為。
自定義繫結:
除了內建繫結以外,使用者還能夠自己選擇將某個外掛目標繫結到生命週期的某個階段上。例如一個常用的外掛 Maven Archetype Plugin,使用者通過這個外掛可以生成一個Maven專案的骨架,也可以從一個現成的專案中生成模板。
通常的用法是使用 mvn archetype:create-from-project 指令生成模板。如果我正在編寫一個模板專案,我希望在打包的時候自動生成模板,那麼我可以把這個目標繫結到default的package生命週期上,如下配置:
</plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>create-archetype</id>
<phase>package</phase>
<goals>
<goal>create-from-project</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
在POM的build元素下的plugins子元素中宣告外掛的使用,除了配置外掛的座標宣告外,還有外掛的執行配置,executeions下每個execution子元素可以用來配置執行一個任務。我們配置了一個id為create-archetype的任務,通過phrase配置,將其繫結到package生命週期階段上,再通過goals配置指定要執行的外掛目標。
執行 mvn clean package 就能看到有以下輸出:
//......以上省略...... [INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ demo --- [INFO] Building jar: /Users/yrw/Desktop/github/demo/target/demo-1.0-SNAPSHOT.jar [INFO] [INFO] >>> maven-archetype-plugin:3.0.1:create-from-project (create-archetype) > generate-sources @ demo >>> [INFO] [INFO] <<< maven-archetype-plugin:3.0.1:create-from-project (create-archetype) < generate-sources @ demo <<< [INFO] [INFO] [INFO] --- maven-archetype-plugin:3.0.1:create-from-project (create-archetype) @ demo --- [INFO] Setting default groupId: com.yrw [INFO] Setting default artifactId: demo [INFO] Setting default version: 1.0-SNAPSHOT [INFO] Setting default package: com.yrw.test [INFO] Scanning for projects... [INFO] [INFO] -----------------------< com.yrw:demo-archetype >----------------------- [INFO] Building demo-archetype 1.0-SNAPSHOT [INFO] --------------------------[ maven-archetype ]--------------------------- [INFO] [INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ demo-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 84 resources [INFO] [INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ demo-archetype --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 2 resources [INFO] [INFO] --- maven-archetype-plugin:3.0.1:jar (default-jar) @ demo-archetype --- [INFO] Building archetype jar: /Users/yrw/Desktop/github/demo/target/generated-sources/archetype/target/demo-archetype-1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.110 s [INFO] Finished at: 2018-11-23T22:12:15+08:00 [INFO] ------------------------------------------------------------------------ [INFO] Archetype project created in /Users/yrw/Desktop/github/demo/target/generated-sources/archetype [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.689 s [INFO] Finished at: 2018-11-23T22:12:15+08:00 [INFO] ------------------------------------------------------------------------
可以看到,在打包的時候執行了archetype:create-from-project,進入/target/generated-sources/archetype目錄,就能看到生成的模板了。
命令列配置外掛:
外掛目標支援命令列配置,可以通過-D引數,並伴隨一個引數=引數值的形式,來配置外掛目標的引數。例如命令 mvn install -Dmaven.test.skip=true ,就會跳過執行測試。
在pom中配置全域性外掛:
並不是所有的外掛引數都適合從命令列配置,有些引數的值從專案釋出都不會改變,對於這種情況,可以在pom檔案中一次性配置。例如需要配置maven-compiler-plugin編譯java1.8.
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> <plugins> <build>
這樣,不管繫結到compile階段的maven-compiler-plugin:compile任務,還是繫結到test-compiler階段的maven-compiler-plugin:testCompiler任務,就都能夠使用該配置,基於1.8版本進行編譯。