深入淺出 Apache Maven 的 Plugins 外掛機制

Apache Maven 之所以強大,是因為他有一個強大的 Plugin 執行框架,你任何想讓 Maven 幫你完成的工作,無論是建置(Build)、封裝(Packaging)、產生報表(Reporting)、執行測試(Tests),全部都是透過 Plugins 完成的。它除了內建的核心 Plugins 之外,還有數以百計的第三方 Plugins 可以安裝使用。今天這篇文章我就來介紹一下他的基本架構與使用方式。

簡介 Apache Maven Plugins

基本上 Apache Maven 的 Plugins 分成兩大類,並且可以定義在專案的 pom.xml 檔案中:

  1. 建置外掛 (Build plugins)

    用來執行在 建置 (build)過程中的所有大小事,他會定義在 POM 檔的 <build/> 元素底下。

  2. 報表外掛 (Reporting plugins)

    用來執行在建立 文件網站 (site)過程中的所有大小事,他會定義在 POM 檔的 <reporting/> 元素底下。

    由於 報表外掛 (Reporting plugins)的結果會被發佈在 文件網站 (site)上,所以必須考量 多國語系 (internationalized)與 本地化 (localized)的要求。詳見 Localization of Plugins 說明。

Apache Maven 官方支援許多 Plugins,並且詳細列在 Available Plugins 頁面中,光是這些內建的 Plugins 就可以幫我們解決 95% 以上的建置或報表工作,真的相當厲害且富有內涵,我很難在一篇文章內介紹這麼多 Plugins,只能淺淺帶過,有興趣大家可以個別研究不同的 Plugins。

突然覺得可以所有 Plugins 都介紹的話,那就可以參加 2022 iThome 鐵人賽 了吧!:sweat_smile:

以下我就列出這些官方支援的 Plugins 清單,大家可以看的大概,有點印象即可:

  • 核心外掛 (Core plugins)

    Plugin類型摘要說明
    compiler建置Compiles Java sources.
    deploy建置Deploy the built artifact to the remote repository.
    failsafe建置Run the JUnit integration tests in an isolated classloader.
    install建置Install the built artifact into the local repository.
    resources建置Copy the resources to the output directory for including in the JAR.
    site建置Generate a site for the current project.
    surefire建置Run the JUnit unit tests in an isolated classloader.
    verifier建置Useful for integration tests - verifies the existence of certain conditions.
    clean建置Clean up after the build.
  • 封裝外掛 (Packaging types/tools)

    Plugin類型摘要說明
    jar建置Build a JAR ( Java ARchive ) from the current project.
    war建置Build a WAR ( Web Application Archive ) from the current project.
    ear建置Generate an EAR ( Enterprise ARchive ) from the current project.
    ejb建置Build an EJB (and optional client) from the current project.
    rar建置Build a RAR ( Resource Adapter Archive ) from the current project.
    app-client/acr建置Build a JavaEE application client from the current project.
    shade建置Build an Uber-JAR from the current project, including dependencies.
    source建置Build a source-JAR from the current project.
    jlink建置Build Java Run Time Image .
    jmod建置Build Java JMod files.
  • 報表外掛 (Reporting plugins)

    Plugin類型摘要說明
    changelog報表Generate a list of recent changes from your SCM.
    changes建置+報表Generate a report from an issue tracker or a change document.
    checkstyle建置+報表Generate a Checkstyle report.
    doap建置Generate a Description of a Project (DOAP) file from a POM.
    docck建置Documentation checker plugin.
    javadoc建置+報表Generate Javadoc for the project.
    jdeps建置Run JDK's JDeps tool on the project.
    jxr建置Generate a source cross reference.
    linkcheck建置Generate a Linkcheck report of your project's documentation.
    pmd建置+報表Generate a PMD report.
    project-info-reports報表Generate standard project reports.
    surefire-report報表Generate a report based on the results of unit tests.
  • 工具外掛 (Tools)

    Plugin類型Description
    antrun建置Run a set of ant tasks from a phase of the build.
    artifact建置Manage artifacts tasks like buildinfo.
    archetype建置Generate a skeleton project structure from an archetype .
    assembly建置Build an assembly (distribution) of sources and/or binaries.
    dependency建置+報表Dependency manipulation (copy, unpack) and analysis.
    enforcer建置Environmental constraint checking (Maven Version, JDK etc), User Custom Rule Execution.
    gpg建置Create signatures for the artifacts and poms.
    help建置Get information about the working environment for the project.
    invoker建置+報表Run a set of Maven projects and verify the output.
    jarsigner建置Signs or verifies project artifacts.
    jdeprscan建置Run JDK's JDeprScan tool on the project.
    patch建置Use the gnu patch tool to apply patch files to source code.
    pdf建置Generate a PDF version of your project's documentation.
    plugin建置+報表Create a Maven plugin descriptor for any mojos found in the source tree, to include in the JAR.
    release建置Release the current project - updating the POM and tagging in the SCM.
    remote-resources建置Copy remote resources to the output directory for inclusion in the artifact.
    scm建置Execute SCM commands for the current project.
    scm-publish建置Publish your Maven website to a scm location.
    scripting建置The Maven Scripting Plugin wraps the Scripting API according to JSR223.
    stage建置Assists with release staging and promotion.
    toolchains建置Allows to share configuration across plugins.
    wrapper建置Download and unpack the maven wrapper distribution

除了 Maven 官方支持的 Plugins 外,還有個 MojoHaus Maven Plugins Project 由社群維護了一系列好用的 Plugins ,有空的時候去翻看看,搞不好有意外之喜。在這個 MojoHaus 的世界裡所稱呼的 Mojo ( Maven plain Old Java Object ) 通常是指 Plugin 中的某個 Goal 實作,很多 Plugin 的 Goal 在實作的時候也會以 ___Mojo 結尾,來當成 Goal 的方法名稱,是一種 Maven plugins 常見的命名規則。我們其實經常會在許多文件中看到這個單字,而這個 Mojo 單字有「魔力」、「魅力」等含意!

認識 Maven 的建置生命週期( lifecycle )、階段( phase )與目標( goal )

在 Maven 裡面有許多「抽象概念」經常會混淆著初學者,因為你只要沒有認真看懂這些概念,根本就無法好好的使用 Maven 這套優異的建置工具。

首先,你要先知道 Maven 定義了三種不同的 生命週期 ,彼此相關而不重複:

  1. default

    處理專案的 建置 (build)與 部署 (deployment)等工作

  2. clean

    處理專案的清理工作,將建置過程中產生的檔案清除

  3. site

    處理專案文件網站的產生工作

你從官網的 Lifecycles Reference 文件可以發現,每個不同的 生命週期 ( lifecycle )分別定義了一系列依序執行的 階段 ( phase ),這些 階段 是 Maven 依據過往數十年的最佳實務整理出來的寶貴經驗。

請注意,這些所謂的「生命週期」與「階段」都只是個「概念」而已,所代表意義是:

  1. 當你想要 建置 與 部署 時 ( default ),你必須依據 Maven 所定義的 階段 來執行任務

    <phases>
      <phase>validate</phase>
      <phase>initialize</phase>
      <phase>generate-sources</phase>
      <phase>process-sources</phase>
      <phase>generate-resources</phase>
      <phase>process-resources</phase>
      <phase>compile</phase>
      <phase>process-classes</phase>
      <phase>generate-test-sources</phase>
      <phase>process-test-sources</phase>
      <phase>generate-test-resources</phase>
      <phase>process-test-resources</phase>
      <phase>test-compile</phase>
      <phase>process-test-classes</phase>
      <phase>test</phase>
      <phase>prepare-package</phase>
      <phase>package</phase>
      <phase>pre-integration-test</phase>
      <phase>integration-test</phase>
      <phase>post-integration-test</phase>
      <phase>verify</phase>
      <phase>install</phase>
      <phase>deploy</phase>
    </phases>

  2. 當你想要 清理 時 ( clean ),你必須依據 Maven 所定義的 階段 來執行任務

    <phases>
      <phase>pre-clean</phase>
      <phase>clean</phase>
      <phase>post-clean</phase>
    </phases>
    <default-phases>
      <clean>
        org.apache.maven.plugins:maven-clean-plugin:2.5:clean
      </clean>
    </default-phases>

  3. 當你想要 建立文件網站 時 ( site ),你必須依據 Maven 所定義的 階段 來執行任務

    <phases>
      <phase>pre-site</phase>
      <phase>site</phase>
      <phase>post-site</phase>
      <phase>site-deploy</phase>
    </phases>
    <default-phases>
      <site>
        org.apache.maven.plugins:maven-site-plugin:3.3:site
      </site>
      <site-deploy>
        org.apache.maven.plugins:maven-site-plugin:3.3:deploy
      </site-deploy>
    </default-phases>

請注意: 所有的 階段 ( phase )其名稱都是不重複的。

瞭解了這些 生命週期 與 階段 的概念之後,你就必須知道,所有的 Java 專案都可以依據實際的需求來定義 特定階段 ( phase )要執行什麼樣的 目標 ( goal )!

所以, 生命週期 ( lifecycle )與 階段 ( phase )就只是個 概念 (Concepts),而 目標 ( goal )才是你真正要做的事情 (要達成的目標)!

我用一個非常簡單的例子來說明:

  1. 我們用以下命令建立一個全新的 Java 專案

    mvn archetype:generate -B `
      '-DarchetypeCatalog=internal' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo1' `
      '-Dversion=1.0-SNAPSHOT'

    由於 Maven 預設會採用 org.apache.maven.archetypes:maven-archetype-quickstart:1.0 這個專案範本( archetype ),所以不用寫底下這段較長的命令:

    mvn archetype:generate -B `
      '-DarchetypeCatalog=internal' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo1' `
      '-Dversion=1.0-SNAPSHOT' `
      '-DarchetypeGroupId=org.apache.maven.archetypes' `
      '-DarchetypeArtifactId=maven-archetype-quickstart' `
      '-DarchetypeVersion=1.0'

    這只是一個非常簡單的 Console 專案:

    其 pom.xml 檔案內容如下:

    <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/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.duotify</groupId>
      <artifactId>demo1</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>demo1</name>
      <url>http://maven.apache.org</url>
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>

  2. 然後我們直接執行 mvn 命令,並獲取以下錯誤訊息

    [INFO] Total time:  0.133 s
    [INFO] Finished at: 2022-09-11T18:04:06+08:00
    [INFO] ------------------------------------------------------------------------
    [ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException

    這裡的重點在這段:

    No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal> . Available lifecycle phases are: validate , initialize , generate-sources , process-sources , generate-resources , process-resources , compile , process-classes , generate-test-sources , process-test-sources , generate-test-resources , process-test-resources , test-compile , process-test-classes , test , prepare-package , package , pre-integration-test , integration-test , post-integration-test , verify , install , deploy , pre-clean , clean , post-clean , pre-site , site , post-site , site-deploy .

    這段英文應該不難理解,你必須在 mvn 命令後面指定一個 phase 或 goal 才能執行 Maven!

  3. 假設我們只要編譯目前的專案,那我們可以指定 compile 這個 階段

    mvn compile

    上述命令執行時會掛掉,容後補充說明。

    由於這個 compile 階段 隸屬於 default 生命週期,因此 Maven 就會從 default 生命週期的第一個 phase 開始找尋是否有相對應的 目標 ( goal )需要達成。

    所以 Maven 會依序去查找 validate , initialize , generate-sources , process-sources , generate-resources , process-resources , compile 這幾個 階段 是否有相對應的 目標 ( goal )去執行程式。

    基本上,整個 Maven 就是這樣跑起來的!:+1:

此時重點就要登場了,所以我們所說的 目標 ( goal )具體來說到底是什麼呢?

理解 Plugin 與 Goal 之間的關係

事實上,我們註冊到 pom.xml 的每一個 Plugins,裡面分別都「實作」了一個到多個 目標 ( goals ),而這些 Plugin 裡面的 目標 ( goals )會明確綁定到特定 階段 ( phase ),當 Maven 執行到該 階段 ( phase )的時候,就會自動執行這個 Plugin 的 目標 ( goal )。說穿了,所謂的 目標 ( goal )就是一個類別中的 方法 而已。

一般來說,在 Plugin 裡面的 目標名稱 ( goal name )經常會跟 階段名稱 ( phase name )刻意設計的一樣,這樣也比較好辨識,但這並不是必要條件。

我以 Apache Maven Compiler Plugin 為例,這個 Plugin 實作了 3 個目標 :

  1. compiler:compile

    用來綁定 compile phase 並用來編譯 Java 主程式 的原始碼( src/main/** )。

  2. compiler:testCompile

    用來綁定 test-compile phase 並用來編譯 Java 測試程式 的原始碼( src/test/** )。

  3. compiler:help

    用來顯示這個 compiler plugin 的使用說明。

    幾乎所有 Plugin 都會實作 help 這個目標( goal ),方便開發人員查詢相關用法。你可以執行 mvn compiler:help 查詢相關用法。

有趣的地方在於,在官網的 Plugin Documentation 文件中,並沒有明確跟你說這些 Goal 要怎樣使用、用在哪裡,這些細節已經被定義在 Maven 的生命週期( lifecycle )、階段( phase )與目標( goal )之中了。因此你若沒有先建立好完整且清晰的概念,就會無法理解 Maven 的運作原理。

我們接續上一段的例子,當我們執行 mvn compile 命令的時候,實際上完整的流程如下:

  1. 先選中 compile 階段( phase ),藉此判斷出 default 這個生命週期( lifecycle )

  2. 依序執行 default 生命週期( lifecycle )的每個階段( phase )

    1. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 validate 階段( phase )的目標( goal )
    2. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 initialize 階段( phase )的目標( goal )
    3. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 generate-sources 階段( phase )的目標( goal )
    4. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 process-sources 階段( phase )的目標( goal )
    5. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 generate-resources 階段( phase )的目標( goal )
    6. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 process-resources 階段( phase )的目標( goal )
    7. 找尋所有 Plugins 中是否有 實作 並 綁定 任何名稱為 compile 階段( phase )的目標( goal )

如此一來 mvn compile 命令便執行完畢!

由於 compile plugin 是 Maven 的核心 plugins 之一,所以預設就會註冊在 pom.xml 之中,不用特別設定,而上述過程只有 compile 這個目標( goal )有被比對中,因此到 compile 這個階段( phase )的時候,就會跑去執行 compile:compile 目標( goal )。

如果我直接執行 mvn compile:compile 的話,就代表我們執行的是 compile 這個 plugin 的 compile 目標而已,不會去執行其他階段(phase),因此也不會去執行其他 Plugins 中的任何目標。

所以 mvn compile 與 mvn compile:compile 所代表的 意義 是截然不同的!

解決無法編譯的問題

我先前有提到,這個範例專案其實無法編譯,你在執行 mvn compile 的時候會發現以下訊息:

[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------< com.duotify:demo1 >--------------------------
[INFO] Building demo1 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ demo1 ---
[WARNING] Using platform encoding (MS950 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory G:\Projects\demo1\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ demo1 ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding MS950, i.e. build is platform dependent!
[INFO] Compiling 1 source file to G:\Projects\demo1\target\classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.991 s
G:\Projects\demo1>mvn compile:compile
[INFO] Scanning for projects...
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (14 kB at 14 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (21 kB at 21 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.733 s
[INFO] Finished at: 2022-09-11T18:40:45+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'compile' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (C:\Users\wakau\.m2\repository), central (https://repo.maven.apache.org/maven2)] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException

你可以從上述訊息得知,其實這個 mvn compile 在執行的過程中,執行了 2 個目標:

maven-resources-plugin:2.6:resources
maven-compiler-plugin:3.1:compile

而在執行 maven-compiler-plugin:3.1:compile 目標時,卻發生了以下錯誤:

[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.

首先,看起來 Maven 內建的 maven-compiler-plugin 選用了 3.1 版本有點過於老舊,他預設使用 Java 5 來編譯原始碼,但我的電腦裝的是 JDK 17 ,編譯器最低支援版本從 Java 7 開始支援,所以才會編譯失敗。

要解決這個問題其實很簡單,只要在專案的 pom.xml 加入這個 maven-compiler-plugin plugin 並提供選項設定即可。

我打算加入以下 XML 片段到 pom.xml 檔案中,藉此指定最新版的 maven-compiler-plugin plugin:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
      </plugin>
    </plugins>
  </build>
  ...
</project>

再重新執行一次 mvn compile 就會發現專案已經可以成功建置!

其實為了讓建置過程可以更穩定,一般來說我們會明確指定各個 Plugins 的版本資訊( <version>3.10.1</version> ),否則當 Plugin 版本變化時,若是遇到 破壞性更新 (Breaking changes)那就遭了!

除了指定 maven-compiler-plugin plugin 到最新版本外,你也可以透過 plugin 的 <configuration> 來指定參數,讓 maven-compiler-plugin 可以選用 1.7 當成我們的原始碼版本,這樣也能讓專案順利編譯成功!

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>8</source>
          <target>8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>

再重新執行一次 mvn compile 或 mvn clean compile 也會發現專案依然可以成功建置!

注意: 執行 mvn clean compile 命令意味著先執行 clean 階段,再執行 compile 階段!

除了上述兩種方法外,還有一種直接透過 CLI 傳入 -D 指定 maven.compiler.source 與 maven.compiler.target 屬性的用法,也可以在執行時動態改變 編譯器版本 設定,詳見 compiler:compile 的 Optional Parameters 說明:

mvn clean compile '-Dmaven.compiler.source=8' '-Dmaven.compiler.target=8'

這個方法也可以通過編譯!

將應用程式封裝成 JAR 檔

最後,我想在多介紹 Apache Maven JAR Plugin ,如果我們想要把應用程式打包成 JAR 檔,就需要用到這個內建的 plugin,以本文的範例來說,還需要對這個 plugin 做出一些調整才行。

你至少需要加入以下設定到 pom.xml 的 <project><build><plugins> 底下:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.duotify.App</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

注意: 其實 <groupId>org.apache.maven.plugins</groupId> 是可以省略的,因為 org.apache.maven.plugins 這個 groupId 是 Maven 的 預設值 。

然後執行以下 mvn clean package 命令即可產生 target\demo1-1.0-SNAPSHOT.jar 檔:

mvn clean package '-Dmaven.compiler.source=8' '-Dmaven.compiler.target=8'

接著就可以用以下命令直接測試執行:

java -jar target/demo1-1.0-SNAPSHOT.jar

總結

有了上述這個完整的例子,我相信你應該已經學會基本的 Maven Plugins 的運作架構與基本設定方法!:+1:

另外,你可以試試執行以下命令,他可以幫你找出你目前專案最終生效的 POM 檔完整內容,包含那些 Maven 內建的 POM 設定值,都會出現在執行結果中:

mvn help:effective-pom

上述命令事實上是執行 help plugin 的 effective-pom 目標( goal )!

你還可以利用以下命令,找出特定一個 階段 ( phase )是哪些 plugins 有綁定 目標 ( goal )

mvn help:describe -Dcmd=compile

他會顯示相當清楚的結果:

[INFO] 'compile' is a phase corresponding to this plugin:
org.apache.maven.plugins:maven-compiler-plugin:3.1:compile

It is a part of the lifecycle for the POM packaging 'jar'. This lifecycle includes the following phases:
* validate: Not defined
* initialize: Not defined
* generate-sources: Not defined
* process-sources: Not defined
* generate-resources: Not defined
* process-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:resources
* compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:compile
* process-classes: Not defined
* generate-test-sources: Not defined
* process-test-sources: Not defined
* generate-test-resources: Not defined
* process-test-resources: org.apache.maven.plugins:maven-resources-plugin:2.6:testResources
* test-compile: org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile
* process-test-classes: Not defined
* test: org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
* prepare-package: Not defined
* package: org.apache.maven.plugins:maven-jar-plugin:2.4:jar
* pre-integration-test: Not defined
* integration-test: Not defined
* post-integration-test: Not defined
* verify: Not defined
* install: org.apache.maven.plugins:maven-install-plugin:2.4:install
* deploy: org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值