Maven的生命周期與自定義插件實(shí)現(xiàn)方法
Maven 的生命周期
maven 將項(xiàng)目的生命周期(Lifecycle)抽象為了三種,每種生命周期中又包含了多個(gè)階段(Phase)。也就是說(shuō)生命周期與階段的關(guān)系是一對(duì)多的。
生命周期的種類(lèi) 與 不同生命周期的所有階段都可以在maven提供的實(shí)現(xiàn)自定義插件需要用到的依賴(lài)中的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 : 用于構(gòu)建前,清除一些資源
*/
// 執(zhí)行clean前要完成的事
PRE_CLEAN("pre-clean"),
// 移除上一次構(gòu)建的文件
CLEAN("clean"),
// 執(zhí)行clean后要完成的事
POST_CLEAN("post-clean"),
/**
* 2. Default (build) lifecycle : 用于構(gòu)建應(yīng)用
*/
VALIDATE("validate"),
INITIALIZE("initialize"),
// 生成源代碼,含在編譯階段中的生成的源代碼,比如通過(guò)APT技術(shù)生成的代碼。
// APT是在javac程序在編譯期間掃描指定注解,并配合自定義的繼承了AbstractProcessor的能夠處理特定注解處理器類(lèi),生成源代碼文件的一種技術(shù)。
// 當(dāng)我們使用maven配置生成處理器并生成了源代碼時(shí),maven會(huì)在target/generated-sources下特殊分類(lèi)展示這些源代碼文件。僅是方便查看,
// 生成的源代碼文件依舊在指定的生成目錄下,并不是在target/generated-sources目錄下。
GENERATE_SOURCES("generate-sources"),
// 處理源代碼
PROCESS_SOURCES("process-sources"),
// 生成資源文件
GENERATE_RESOURCES("generate-resources"),
// 處理資源文件,例:復(fù)制到目標(biāo)目錄下:src/main/resources/* --> target/classes,為打包做好準(zhǔn)備
PROCESS_RESOURCES("process-resources"),
// 編譯源代碼
COMPILE("compile"),
// 處理編譯后的類(lèi)文件
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"),
// 安裝:打包后的項(xiàng)目安裝到本地倉(cāng)庫(kù),后期可以使用本地依賴(lài)
INSTALL("install"),
// 部署:將打包后的項(xiàng)目推送到遠(yuǎn)程倉(cāng)庫(kù)
DEPLOY("deploy"),
/**
* 3. Site lifecycle(很少用) : 將 POM 可以包含的各種項(xiàng)目信息,例如:項(xiàng)目描述,開(kāi)發(fā)者信息等(pom中可以使用的描述標(biāo)簽)。通過(guò) Maven 提供的 maven-site-plugin 插件讓 Maven 生成一個(gè) Web
* 站點(diǎn)(生成一組靜態(tài)文件)。并能推送到遠(yuǎn)程。
*/
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;
}
}每個(gè)階段的執(zhí)行依賴(lài)前面的所有階段的執(zhí)行結(jié)果,比如:mvn clean,會(huì)先執(zhí)行pre-clean。mvn post-clean,會(huì)先執(zhí)行pre-clean & clean。
常用命令的區(qū)別
clean:刪除項(xiàng)目路徑下的target文件,但不會(huì)刪除本地的maven倉(cāng)庫(kù)已經(jīng)install生成的jar文件
compile:無(wú)論之前是否編譯過(guò),都會(huì)在項(xiàng)目路徑下生成一個(gè)target目錄,該目錄下含有一個(gè)classes文件夾,編譯生成的class文件都放在這里。
package:基于compile命令的功能,同時(shí)會(huì)在target目錄下生成項(xiàng)目的jar或war包??赡艽嬖诖虬幾g失敗的問(wèn)題:A項(xiàng)目依賴(lài)B項(xiàng)目,打包A項(xiàng)目,發(fā)現(xiàn)引入B項(xiàng)目,繼而打包B項(xiàng)目。根據(jù)B項(xiàng)目打包出的Jar或War包只存在B項(xiàng)目的target目錄下,所以當(dāng)打包完B項(xiàng)目繼續(xù)編譯A項(xiàng)目時(shí)就會(huì)報(bào)錯(cuò),因?yàn)檎也坏剿蕾?lài)的B項(xiàng)目的打包結(jié)果。本質(zhì)原因就在于,B項(xiàng)目的打包結(jié)果沒(méi)有在本地倉(cāng)庫(kù)中,maven找不到所需B項(xiàng)目依賴(lài)。需要通過(guò)install命令解決,也說(shuō)明一個(gè)問(wèn)題:打包一個(gè)項(xiàng)目時(shí),先install沒(méi)有在本地倉(cāng)庫(kù)中的依賴(lài)。
install:基于package命令的功能,同時(shí)會(huì)在本地maven倉(cāng)庫(kù)生成jar文件。
組合使用:
mvn clean package
mvn clean install
關(guān)于maven命令,個(gè)人理解就是在執(zhí)行命令關(guān)聯(lián)的插件中的某些goal。
什么是 Maven plugin
Maven Plugin本質(zhì)上也是一個(gè)Maven project,打包后也就是一個(gè)jar包,幫助我們完成某些工作。
當(dāng)我們通過(guò)idea自己定義一個(gè)插件maven項(xiàng)目時(shí),可以選擇archetype(原型)選項(xiàng)為:org.apache.maven.archetypes:maven-archetype-plugin
。idea 會(huì)根據(jù)此選項(xiàng)幫助我們快速搭建出一個(gè)插件項(xiàng)目的結(jié)構(gòu)。注意觀察:org.apache.maven.archetypes:maven-archetype-plugin,不就是一個(gè)maven 坐標(biāo)嘛。
是的,可以在本地的maven倉(cāng)庫(kù)根據(jù)這個(gè)坐標(biāo),找到對(duì)應(yīng)的jar包。而jar包中的內(nèi)容,就是idea要給我們生成的項(xiàng)目骨架。
Maven插件的類(lèi)型也分為兩種:
Build plugin : 用于構(gòu)建項(xiàng)目工程,在<build>標(biāo)簽中配置的<plugin>
Reporting plugin : 用于生成網(wǎng)站內(nèi)容(site),在<reporting>標(biāo)簽中配置的<plugin>
Build類(lèi)型Maven plugin與生命周期的關(guān)系
上面說(shuō)到,插件會(huì)幫助我們完成一些工作,那么完成什么樣的工作?什么時(shí)間節(jié)點(diǎn)運(yùn)行?
以maven的生命周期為例:
- 所有生命周期的所有階段的工作都是由maven自帶的Build類(lèi)型插件完成的。也就是說(shuō),maven定義了一套接口,具體實(shí)現(xiàn)由插件完成。
- 根據(jù)生命周期的多個(gè)階段的執(zhí)行順序,序執(zhí)行具體的實(shí)現(xiàn)插件。
對(duì)于我們自己實(shí)現(xiàn)的Build類(lèi)型插件,也必須要掛在到某個(gè)階段上。也就是說(shuō),maven的Build插件是需要綁定到生命周期中的某個(gè)階段上觸發(fā)執(zhí)行的。
那么在引出一個(gè)問(wèn)題:一個(gè)Build插件工程只能為一個(gè)生命周期階段服務(wù)嘛?并不是。一個(gè)工程中可以編寫(xiě)服務(wù)于不同階段的功能代碼,每一個(gè)實(shí)現(xiàn)可以稱(chēng)之為一個(gè)goal。而且多個(gè)goal是可以掛到同個(gè)phase上的。
那么可以整理出這樣一種關(guān)系:Lifecycle 1:N -> Phase 1:N -> Goal
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的自定義插件
如果能理解上面的描述,那么下面的插件代碼其實(shí)就很好理解了,甚至不需要太多的解釋描述。
一、創(chuàng)建一個(gè)Maven plugin工程,我們不討論過(guò)舊的基于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插件類(lèi)庫(kù) -->
<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)建一個(gè)goal插件類(lèi):
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名稱(chēng) & 生效階段
- Parameter注解:引入插件的項(xiàng)目中,對(duì)于引入插件配置的
<configuration><configuration/>節(jié)點(diǎn)中的子節(jié)點(diǎn)配置項(xiàng)(在后面的測(cè)試工程中會(huì)體現(xiàn)出來(lái)) - 重寫(xiě)execute方法
一個(gè)簡(jiǎn)單的插件工程就算完成了,是不是很簡(jiǎn)單。
三、創(chuàng)建測(cè)試工程
先將插件項(xiàng)目install在本地,測(cè)試工程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)一個(gè)問(wèn)題:集合元素中子元素的標(biāo)簽名稱(chēng)是比較寬泛的。但根據(jù)一般的命名規(guī)范來(lái)說(shuō),都會(huì)將子元素統(tǒng)一更名為:option -->
<option1>O1</option1>
<option2>OP2</option2>
<option3>OPT3</option3>
</options>
</configuration>
<!-- 配置需要執(zhí)行插件中的那些goal -->
<executions>
<execution>
<!-- 執(zhí)行id -->
<id>exeCustomMojoId</id>
<!-- 生效階段,不指定則取插件類(lèi)的@Mojo注解中的defaultPhase。此處專(zhuān)門(mén)設(shè)定了一個(gè)與defaultPhase不同的階段值 -->
<phase>clean</phase>
<!-- 需要運(yùn)作的Goal -->
<goals>
<goal>customMojo</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
測(cè)試工程不需要查看項(xiàng)目代碼的執(zhí)行情況,專(zhuān)注于maven的打印日志即可。
執(zhí)行g(shù)oal掛載的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 上打印了我們?cè)谧远x插件中的輸出內(nèi)容。
到此這篇關(guān)于Maven的生命周期與自定義插件實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Maven生命周期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Java線程池如何實(shí)現(xiàn)優(yōu)雅退出
這篇文章我們將從源碼角度深度解析線程池是如何優(yōu)雅的退出程序的,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)java線程池有一定幫助,需要的可以參考一下2022-07-07
Java Web Fragment在項(xiàng)目中使用方法詳解
這篇文章主要介紹了Web Fragment在項(xiàng)目中使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Java中的DelayQueue實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景詳解
這篇文章主要介紹了Java中的DelayQueue實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景詳解,DelayQueue是一個(gè)沒(méi)有邊界BlockingQueue實(shí)現(xiàn),加入其中的元素必需實(shí)現(xiàn)Delayed接口,當(dāng)生產(chǎn)者線程調(diào)用put之類(lèi)的方法加入元素時(shí),會(huì)觸發(fā)Delayed接口中的compareTo方法進(jìn)行排序,需要的朋友可以參考下2023-12-12
java web實(shí)現(xiàn)簡(jiǎn)單留言板功能
這篇文章主要為大家詳細(xì)介紹了java web實(shí)現(xiàn)簡(jiǎn)單留言板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
IDEA實(shí)現(xiàn)序列化時(shí)如何自動(dòng)生成serialVersionUID的步驟
這篇文章主要介紹了IDEA實(shí)現(xiàn)序列化時(shí)如何自動(dòng)生成serialVersionUID的步驟,首先安裝GenerateSerialVersionUID插件,當(dāng)出現(xiàn)添加serialVersionUID選項(xiàng),選中則會(huì)自動(dòng)生成serialVersionUID,感興趣的朋友一起學(xué)習(xí)下吧2024-02-02
Java實(shí)現(xiàn)AES/CBC/PKCS7Padding加解密的方法
這篇文章主要介紹了Java實(shí)現(xiàn)AES/CBC/PKCS7Padding加解密的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08

