Maven外掛執行方式

wastonl發表於2024-09-20

執行方式

maven外掛執行的最小單元為goal,一個外掛可以有多個goal。執行的方式主要為以下兩種

  • 由maven生命週期驅動,需要外掛相應的goals繫結到具體的生命週期階段中。

    需要外掛和要執行的goal顯示宣告到pom檔案中。

    # 可透過-D傳遞引數給外掛的goal
    mvn package -Dkey=value
    
  • 透過mvn命令顯示執行,外掛可以不用宣告到pom檔案中,從倉庫中查詢。

    語法形如mvn groupId:artifactId:version:goal -Dkey=value

    groupId:artifactId:version為外掛的座標,其中version可以省略,若專案pom沒有宣告這個外掛,則使用倉庫最新的版本。

    特別的,maven還支援短名稱寫法,不過需要外掛命名(artifactId)遵循一定規則,形如xxx-maven-plugin,官方的外掛為maven-xxx-plugin。這樣命令可以變成mvn xxx:goal -Dkey=value使用短名稱命令時非官方外掛需要在專案pom檔案中宣告外掛,否則需要配置外掛字首才能使用。

    # 執行外掛的hello這個goal
    mvn com.wangtao:demo-maven-plugin:1.0.0:hello
    # 短名稱形式, 由於外掛遵循了maven的命名機制
    mvn demo:hello
    

    短名稱形式需要在pom宣告外掛,不需要宣告goal,goal由命令明確指定。

    <build>
      <plugins>
        <plugin>
          <groupId>com.wangtao</groupId>
          <artifactId>demo-maven-plugin</artifactId>
          <version>1.0-SNAPSHOT</version>
        </plugin>
      </plugins>
    </build>
    

外掛命名

官方外掛命名形如maven-xxx-plugin,比如maven-jar-plugin、maven-clean-plugin。

非官方外掛命名形如xxx-maven-plugin,比如spring-boot-maven-plugin。

遵循這樣的命名規則可以使用短名稱執行外掛。

外掛的goal繫結生命週期

兩種方式

  • 可以在編寫goal時使用@Mojo註解的defaultPhase屬性繫結一個生命週期,要想goal執行,還是需要在pom檔案中宣告這個goal才行,官方的一些外掛由於在super pom已經宣告,所以可以不用寫。

    @Mojo(name = "bindPhase", defaultPhase = LifecyclePhase.PACKAGE)
    public class BindPhaseMojo extends AbstractMojo {
    }
    

    pom使用如下

    <build>
      <plugins>
        <plugin>
          <groupId>com.wangtao</groupId>
          <artifactId>demo-maven-plugin</artifactId>
          <version>1.0-SNAPSHOT</version>
          <executions>
            <execution>
              <id>default-bindPhase</id>
              <!-- 宣告要執行的goal,可以不用指定phase標籤 -->
              <goals>
                <goal>bindPhase</goal>
              </goals>
              <configuration>
                <greeting>hello maven plugin</greeting>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    
  • 在pom檔案中指定,可以覆蓋掉預設的繫結值

    <build>
      <plugins>
        <plugin>
          <groupId>com.wangtao</groupId>
          <artifactId>demo-maven-plugin</artifactId>
          <version>1.0-SNAPSHOT</version>
          <executions>
            <execution>
              <id>default-bindPhase</id>
              <!-- 使用phase標籤明確繫結生命週期 -->
              <phase>package</phase>
              <goals>
                <goal>bindPhase</goal>
              </goals>
              <configuration>
                <greeting>hello maven plugin</greeting>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
    

使用外掛名的命令方式執行外掛中的goal

有時執行外掛時需要前置任務,怎麼觸發呢,比如spring-boot-maven-plugin:run這個goal,它需要執行程式,勢必要觸發編譯、打包。

可以透過@Execute註解來實現這個效果

@Mojo(name = "hello")
@Execute(phase = LifecyclePhase.PACKAGE)
public class HelloMojo extends AbstractMojo {
}

假設外掛名為demo-maven-plugin。

當執行mvn demo:hello時,先build到package階段(這會觸發中間各個階段繫結的goal), 然後執行hello這個goal。

引數

引數可以配置在專案pom檔案中,也可以在執行時透過-D動態傳參。

引數由@Parameter註解標記,有如下幾個屬性

name:引數名字,不寫就是java欄位名稱

property: jvm系統引數對應的key,可以透過-D動態傳參

defaultValue:預設值

required:引數是否必輸

比如下面外掛的一個goal

@Mojo(name = "bindPhase", defaultPhase = LifecyclePhase.PACKAGE)
public class BindPhaseMojo extends AbstractMojo {

    @Parameter(property = "sayhi.greeting", defaultValue = "Hello World!" )
    private String greeting;

    public void execute() {
        getLog().info("====================BindPhaseMojo execute===================");
        getLog().info(greeting);
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
}

pom檔案配置

<build>
  <plugins>
    <plugin>
      <groupId>com.wangtao</groupId>
      <artifactId>demo-maven-plugin</artifactId>
      <version>1.0-SNAPSHOT</version>
      <executions>
        <execution>
          <id>default-bindPhase</id>
          <goals>
            <goal>bindPhase</goal>
          </goals>
          <configuration>
            <!-- 指定引數值,所有的引數在configuration標籤下面 -->
            <greeting>hello maven plugin</greeting>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

-D動態傳參形式

對應的pom檔案

<build>
  <plugins>
    <plugin>
      <groupId>com.wangtao</groupId>
      <artifactId>demo-maven-plugin</artifactId>
      <version>1.0-SNAPSHOT</version>
      <executions>
        <execution>
          <id>default-bindPhase</id>
          <goals>
            <goal>bindPhase</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
# 透過-D引數動態傳參(該外掛預設繫結到package生命週期)
mvn package -Dsayhi.greeting=hello

注意:pom檔案若明確指定了引數,再透過-D動態傳參,是不會覆蓋掉pom檔案明確指定的值的。

FAQ

  1. <execution>下標籤中的<id>沒有指定值時,預設值為default。

  2. 每一個<execution>標籤下可以宣告多個<goal>,他們共享同一個<configuration><phase>,因此如果需要不一樣的引數,將<goal>放到不同的<execution>下,一個外掛可以配置多個<execution>

  3. <plugin>標籤下的<configuration>引數配置是針對宣告的所有的goal引數配置,不過<execution>標籤下的<configuration>優先順序更高。

    <build>
      <plugins>
        <plugin>
          <groupId>com.wangtao</groupId>
          <artifactId>demo-maven-plugin</artifactId>
          <version>1.0-SNAPSHOT</version>
          <executions>
            <execution>
              <id>default-bindPhase</id>
              <phase>package</phase>
              <goals>
                <goal>bindPhase</goal>
              </goals>
              <!-- 引數區域性配置,優先順序更高 -->
              <configuration>
                <greeting1>hello maven plugin</greeting1>
              </configuration>
            </execution>
          </executions>
          <!-- 外掛引數全域性配置 -->
          <configuration>
            <greeting1>hello1</greeting1>
            <greeting2>hello2</greeting2>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
  4. 命令列-D動態傳參不會覆蓋掉pom檔案中配置的引數值。

  5. 預設繫結生命週期的goal,也要在pom檔案中execution顯示宣告要執行的goal,只不過是<phase>標籤可以省略。官方的外掛之所以可以不用寫,是因為super pom已經做了這個事情。

相關文章