Maven的生命周期與自定義插件實現(xiàn)方法
Maven 的生命周期
maven 將項目的生命周期(Lifecycle)抽象為了三種,每種生命周期中又包含了多個階段(Phase)。也就是說生命周期與階段的關系是一對多的。
生命周期的種類 與 不同生命周期的所有階段都可以在maven提供的實現(xiàn)自定義插件需要用到的依賴中的enum里查看到:
<dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.6.0</version> <scope>provided</scope> </dependency>
public enum LifecyclePhase { /** * 1. Clean lifecycle : 用于構建前,清除一些資源 */ // 執(zhí)行clean前要完成的事 PRE_CLEAN("pre-clean"), // 移除上一次構建的文件 CLEAN("clean"), // 執(zhí)行clean后要完成的事 POST_CLEAN("post-clean"), /** * 2. Default (build) lifecycle : 用于構建應用 */ VALIDATE("validate"), INITIALIZE("initialize"), // 生成源代碼,含在編譯階段中的生成的源代碼,比如通過APT技術生成的代碼。 // APT是在javac程序在編譯期間掃描指定注解,并配合自定義的繼承了AbstractProcessor的能夠處理特定注解處理器類,生成源代碼文件的一種技術。 // 當我們使用maven配置生成處理器并生成了源代碼時,maven會在target/generated-sources下特殊分類展示這些源代碼文件。僅是方便查看, // 生成的源代碼文件依舊在指定的生成目錄下,并不是在target/generated-sources目錄下。 GENERATE_SOURCES("generate-sources"), // 處理源代碼 PROCESS_SOURCES("process-sources"), // 生成資源文件 GENERATE_RESOURCES("generate-resources"), // 處理資源文件,例:復制到目標目錄下:src/main/resources/* --> target/classes,為打包做好準備 PROCESS_RESOURCES("process-resources"), // 編譯源代碼 COMPILE("compile"), // 處理編譯后的類文件 PROCESS_CLASSES("process-classes"), GENERATE_TEST_SOURCES("generate-test-sources"), PROCESS_TEST_SOURCES("process-test-sources"), GENERATE_TEST_RESOURCES("generate-test-resources"), PROCESS_TEST_RESOURCES("process-test-resources"), TEST_COMPILE("test-compile"), PROCESS_TEST_CLASSES("process-test-classes"), TEST("test"), PREPARE_PACKAGE("prepare-package"), // 打包:將編譯后的代碼打包成指定格式的文件包,比如JAR、WAR或者EAR文件 PACKAGE("package"), PRE_INTEGRATION_TEST("pre-integration-test"), INTEGRATION_TEST("integration-test"), POST_INTEGRATION_TEST("post-integration-test"), VERIFY("verify"), // 安裝:打包后的項目安裝到本地倉庫,后期可以使用本地依賴 INSTALL("install"), // 部署:將打包后的項目推送到遠程倉庫 DEPLOY("deploy"), /** * 3. Site lifecycle(很少用) : 將 POM 可以包含的各種項目信息,例如:項目描述,開發(fā)者信息等(pom中可以使用的描述標簽)。通過 Maven 提供的 maven-site-plugin 插件讓 Maven 生成一個 Web * 站點(生成一組靜態(tài)文件)。并能推送到遠程。 */ PRE_SITE("pre-site"), SITE("site"), POST_SITE("post-site"), SITE_DEPLOY("site-deploy"), NONE(""); private final String id; LifecyclePhase(String id) { this.id = id; } public String id() { return this.id; } }
每個階段的執(zhí)行依賴前面的所有階段的執(zhí)行結(jié)果,比如:mvn clean,會先執(zhí)行pre-clean。mvn post-clean,會先執(zhí)行pre-clean & clean。
常用命令的區(qū)別
clean:刪除項目路徑下的target文件,但不會刪除本地的maven倉庫已經(jīng)install生成的jar文件
compile:無論之前是否編譯過,都會在項目路徑下生成一個target目錄,該目錄下含有一個classes文件夾,編譯生成的class文件都放在這里。
package:基于compile命令的功能,同時會在target目錄下生成項目的jar或war包??赡艽嬖诖虬幾g失敗的問題:A項目依賴B項目,打包A項目,發(fā)現(xiàn)引入B項目,繼而打包B項目。根據(jù)B項目打包出的Jar或War包只存在B項目的target目錄下,所以當打包完B項目繼續(xù)編譯A項目時就會報錯,因為找不到所依賴的B項目的打包結(jié)果。本質(zhì)原因就在于,B項目的打包結(jié)果沒有在本地倉庫中,maven找不到所需B項目依賴。需要通過install命令解決,也說明一個問題:打包一個項目時,先install沒有在本地倉庫中的依賴。
install:基于package命令的功能,同時會在本地maven倉庫生成jar文件。
組合使用:
mvn clean package
mvn clean install
關于maven命令,個人理解就是在執(zhí)行命令關聯(lián)的插件中的某些goal。
什么是 Maven plugin
Maven Plugin本質(zhì)上也是一個Maven project,打包后也就是一個jar包,幫助我們完成某些工作。
當我們通過idea自己定義一個插件maven項目時,可以選擇archetype(原型)選項為:org.apache.maven.archetypes:maven-archetype-plugin
。idea 會根據(jù)此選項幫助我們快速搭建出一個插件項目的結(jié)構。注意觀察:org.apache.maven.archetypes:maven-archetype-plugin,不就是一個maven 坐標嘛。
是的,可以在本地的maven倉庫根據(jù)這個坐標,找到對應的jar包。而jar包中的內(nèi)容,就是idea要給我們生成的項目骨架。
Maven插件的類型也分為兩種:
Build plugin : 用于構建項目工程,在<build>
標簽中配置的<plugin>
Reporting plugin : 用于生成網(wǎng)站內(nèi)容(site),在<reporting>
標簽中配置的<plugin>
Build類型Maven plugin與生命周期的關系
上面說到,插件會幫助我們完成一些工作,那么完成什么樣的工作?什么時間節(jié)點運行?
以maven的生命周期為例:
- 所有生命周期的所有階段的工作都是由maven自帶的Build類型插件完成的。也就是說,maven定義了一套接口,具體實現(xiàn)由插件完成。
- 根據(jù)生命周期的多個階段的執(zhí)行順序,序執(zhí)行具體的實現(xiàn)插件。
對于我們自己實現(xiàn)的Build類型插件,也必須要掛在到某個階段上。也就是說,maven的Build插件是需要綁定到生命周期中的某個階段上觸發(fā)執(zhí)行的。
那么在引出一個問題:一個Build插件工程只能為一個生命周期階段服務嘛?并不是。一個工程中可以編寫服務于不同階段的功能代碼,每一個實現(xiàn)可以稱之為一個goal。而且多個goal是可以掛到同個phase上的。
那么可以整理出這樣一種關系:Lifecycle 1:N -> Phase 1:N -> Goal
實現(xiàn)一個簡單的自定義插件
如果能理解上面的描述,那么下面的插件代碼其實就很好理解了,甚至不需要太多的解釋描述。
一、創(chuàng)建一個Maven plugin工程,我們不討論過舊的基于java注釋的配置方式,而是基于注解配置的方式。pom如下:
<project xmlns="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"> <parent> <artifactId>maven-plugin</artifactId> <groupId>life.cqq</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>custom-plugin</artifactId> <packaging>maven-plugin</packaging> <name>custom-plugin</name> <dependencies> <!-- Maven插件類庫 --> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.6.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <!-- 配置插件用的插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>3.5.2</version> <configuration> <!-- 插件執(zhí)行命令前綴 -> mvn prefix:mojoName,例: mvn customPlugin:customMojo --> <goalPrefix>customPlugin</goalPrefix> <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> </configuration> </plugin> </plugins> </build> </project>
注意:<packaging>maven-plugin</packaging>
二、 創(chuàng)建一個goal插件類:
package life.cqq; import java.util.List; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @Mojo(name = "customMojo", defaultPhase = LifecyclePhase.PACKAGE) public class CustomMojo extends AbstractMojo { @Parameter(defaultValue = "${project.build.directory}", property = "args", required = true) private String args; @Parameter(property = "options", required = true) private List<String> options; @Override public void execute() throws MojoExecutionException, MojoFailureException { System.out.println("Custom plugin exec"); System.out.println(args); System.out.println(options); } }
- 繼承AbstractMojo
- 添加@Mojo注解,指定goal名稱 & 生效階段
- Parameter注解:引入插件的項目中,對于引入插件配置的
<configuration><configuration/>
節(jié)點中的子節(jié)點配置項(在后面的測試工程中會體現(xiàn)出來) - 重寫execute方法
一個簡單的插件工程就算完成了,是不是很簡單。
三、創(chuàng)建測試工程
先將插件項目install在本地,測試工程pom如下:
<project xmlns="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"> <parent> <artifactId>maven-plugin</artifactId> <groupId>life.cqq</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>using-plugin</artifactId> <packaging>jar</packaging> <name>using-plugin</name> <build> <plugins> <!-- 引入自定義插件 --> <plugin> <groupId>life.cqq</groupId> <artifactId>custom-plugin</artifactId> <version>1.0-SNAPSHOT</version> <!-- 插件參數(shù)配置 --> <configuration> <args>1</args> <options> <!-- 這里主要想體現(xiàn)一個問題:集合元素中子元素的標簽名稱是比較寬泛的。但根據(jù)一般的命名規(guī)范來說,都會將子元素統(tǒng)一更名為:option --> <option1>O1</option1> <option2>OP2</option2> <option3>OPT3</option3> </options> </configuration> <!-- 配置需要執(zhí)行插件中的那些goal --> <executions> <execution> <!-- 執(zhí)行id --> <id>exeCustomMojoId</id> <!-- 生效階段,不指定則取插件類的@Mojo注解中的defaultPhase。此處專門設定了一個與defaultPhase不同的階段值 --> <phase>clean</phase> <!-- 需要運作的Goal --> <goals> <goal>customMojo</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
測試工程不需要查看項目代碼的執(zhí)行情況,專注于maven的打印日志即可。
執(zhí)行goal掛載的phase:
D:\development\idea\workspace\personal\maven-plugin\using-plugin>mvn clean
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< life.cqq:using-plugin >------------------------
[INFO] Building using-plugin 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ using-plugin ---
[INFO] Deleting D:\development\idea\workspace\personal\maven-plugin\using-plugin\target
[INFO]
[INFO] --- custom-plugin:1.0-SNAPSHOT:customMojo (exeCustomMojoId) @ using-plugin ---
Custom plugin exec
1
[OP1, OP2, OP3]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.228 s
[INFO] Finished at: 2022-09-03T17:32:48+08:00
[INFO] ------------------------------------------------------------------------
直接調(diào)用插件中的goal:
D:\development\idea\workspace\personal\maven-plugin\using-plugin>mvn customPlugin:customMojo
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< life.cqq:using-plugin >------------------------
[INFO] Building using-plugin 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- custom-plugin:1.0-SNAPSHOT:customMojo (default-cli) @ using-plugin ---
Custom plugin exec
1
[OP1, OP2, OP3]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.207 s
[INFO] Finished at: 2022-09-03T17:57:42+08:00
[INFO] ------------------------------------------------------------------------
在 [INFO] BUILD SUCCESS
上打印了我們在自定義插件中的輸出內(nèi)容。
到此這篇關于Maven的生命周期與自定義插件實現(xiàn)方法的文章就介紹到這了,更多相關Maven生命周期內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用mybatis log plugin插件展示出數(shù)據(jù)庫查詢語句方式
本文介紹了如何安裝和配置MyBatis日志插件,包括集成log4j、配置log4j.xml文件和在application.properties中添加數(shù)據(jù)庫打印配置,通過這些步驟,可以在調(diào)試時查看預編譯的數(shù)據(jù)庫語句和實際查詢語句2024-11-11java String類功能、原理與應用案例【統(tǒng)計、判斷、轉(zhuǎn)換等】
這篇文章主要介紹了java String類功能、原理與應用案例,結(jié)合實例形式詳細分析了java String類的基本功能、構造方法,以及使用String類實現(xiàn)統(tǒng)計、判斷、轉(zhuǎn)換等功能相關操作技巧,需要的朋友可以參考下2019-03-03Java concurrency之AtomicLongFieldUpdater原子類_動力節(jié)點Java學院整理
AtomicLongFieldUpdater可以對指定"類的 'volatile long'類型的成員"進行原子更新。它是基于反射原理實現(xiàn)的。下面通過本文給大家分享Java concurrency之AtomicLongFieldUpdater原子類的相關知識,感興趣的朋友一起看看吧2017-06-06mybatis新增到數(shù)據(jù)庫后返回當前ID問題
這篇文章主要介紹了mybatis新增到數(shù)據(jù)庫后返回當前ID問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Java詳細分析Lambda表達式與Stream流的使用方法
Lambda表達式,基于Lambda所帶來的函數(shù)式編程,又引入了一個全新的Stream概念,用于解決集合類庫既有的弊端,Lambda 允許把函數(shù)作為一個方法的參數(shù)(函數(shù)作為參數(shù)傳遞進方法中)。使用 Lambda 表達式可以使代碼變的更加簡潔緊湊2022-04-04Spring boot 應用實現(xiàn)動態(tài)刷新配置詳解
這篇文章主要介紹了spring boot 配置動態(tài)刷新實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2021-09-09