簡體   English   中英

Maven插件前綴解析如何工作? 為什么要解決“ findbugs”而不是“ jetty”?

[英]How does Maven plugin prefix resolution work? Why is it resolving “findbugs” but not “jetty”?

我當時使用Maven進行了一些測試,意識到我可以執行Findbugs插件的findbugs目標,而無需將該插件添加到POM文件中。 另一方面,當我需要運行Jetty插件的run目標時,我被迫將插件添加到POM文件中,或者構建失敗。

  • 為什么Jetty不需要在POM中進行配置,而Findbugs卻不需要?
  • Maven如何知道要執行哪些Findbugs(假設我們必須使用名稱相同但組ID不同的插件)?

當我運行第一個命令時,構建成功,而POM文件中沒有任何更改:

mvn findbugs:findbugs
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building module-mytest 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- findbugs-maven-plugin:3.0.4:findbugs (default-cli) @ module-mytest ---
[INFO] Fork Value is true
     [java] Warnings generated: 6
[INFO] Done FindBugs Analysis....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24.165s
[INFO] Finished at: Sun Oct 23 18:40:26 WEST 2016
[INFO] Final Memory: 21M/111M
[INFO] -----------------------------------------------------------------------

但是當我運行第二個時,我得到了:

mvn jetty:run
[INFO] Scanning for projects...
Downloading: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (13 KB at 30.0 KB/sec)
Downloaded: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (20 KB at 41.0 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.129s
[INFO] Finished at: Sun Oct 23 18:43:27 WEST 2016
[INFO] Final Memory: 12M/104M
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'jetty' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (/home/hp-pc/.m2/repository), central (http://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

因此,為了通過構建,我需要將以下內容添加到pom文件中:

<plugin>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.2.11.v20150529</version>
</plugin>

什么是前綴,為什么我們需要它?

您剛剛遇到了Maven的插件前綴解析 此功能使用戶能夠使用其前綴來調用特定Maven插件的目標。 在命令行上直接調用目標時,可以使用以下功能齊全的形式:

mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar

這將調用Foo Maven插件的目標bar ,其坐標為my.plugin.groupId:foo-maven-plugin:1.0.0 (以groupId:artifactId:version的形式)。 它運作良好,但是有點冗長。 不用指定所有這些坐標就可以以一種更簡單的方式調用此目標,這將是很好的。 Maven通過為插件分配前綴來實現這一點,因此您可以使用以下前綴而不是整個坐標來引用該前綴:

mvn foo:bar
    ^^^ ^^^
     |    |
   prefix |
          |
         goal

如何確定此前綴?

您可以為每個Maven插件定義一個前綴。 這對應於用於標識它的簡單名稱:

使用的常規工件ID格式為:

  • maven-${prefix}-plugin用於由Apache Maven團隊本身維護的官方插件(您不得對插件使用此命名模式,有關更多信息,請參閱此注釋)
  • ${prefix}-maven-plugin用於其他來源的插件

如果您插件的artifactId符合此模式,則Maven將自動將您的插件映射到存儲庫中您插件的groupId路徑中存儲的元數據中的正確前綴。

換句話說,如果您插件的工件ID名為foo-maven-plugin ,則Maven將自動為其分配一個前綴foo 如果您不希望使用此默認分配,則仍然可以在maven-plugin-plugin及其goalPrefix參數的幫助下進行配置。

Maven如何將前綴映射到插件?

在命令中

mvn foo:bar

Maven必須有一種推斷foo實際上是my.plugin.groupId:foo-maven-plugin settings.xml文件中,可以添加插件組 ,形式為:

<pluginGroups>
  <pluginGroup>org.mortbay.jetty</pluginGroup>
</pluginGroups>

這是在告訴Maven當您在命令中使用前綴時應該考慮哪個組ID。 默認情況下,除了設置中指定的組外, Maven還搜索組ID org.apache.maven.pluginsorg.codehaus.mojo 它會在您在設置中配置的默認值之后搜索這些默認值。 因此,使用上述配置以及mvn foo:bar的命令,Maven將在組ID org.mortbay.jettyorg.apache.maven.pluginsorg.codehaus.mojo查找具有foo前綴的插件。 。

第二步是實際執行搜索的方式。 Maven將從這些組ID的每個遠程存儲庫下載元數據文件(如果已下載,則將其查找到本地存儲庫中),稱為maven-metadata.xml 如果以我們僅有的遠程存儲庫為Maven Central的示例為例,則Maven將首先下載http://repo1.maven.org/maven2/org/mortbay/jetty/maven-metadata.xml ,並在此文件中查找我們有一些映射foo東西。 請注意,組ID是如何轉換為遠程存儲庫中的目錄結構的。 該元數據文件的結構為:

<metadata>
  <plugins>
    <plugin>
      <name>Some Awesome Maven Plugin</name>
      <prefix>somePrefix</prefix>
      <artifactId>some-maven-plugin</artifactId>
    </plugin>
  </plugins>
</metadata>

如果<plugin>部分均不包含等於我們指定的<prefix>foo ),則Maven將繼續使用下一個組ID,並點擊http://repo1.maven.org/maven2/org/codehaus/mojo/maven-metadata.xml 再次,如果找不到任何內容,Maven最終會訪問http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-metadata.xml (注意Downloading:登錄到mvn jetty:run命令,准確地獲取最后兩個文件)。 如果仍然找不到任何內容,那么Maven將無法為您做任何事情,並且它將出錯:

[錯誤]在存儲庫[本地(..)中找不到在當前項目和插件組[org.mortbay.jetty,org.apache.maven.plugins,org.codehaus.mojo]中前綴為'foo'的插件。 ./.m2/存儲庫),中央( http://repo.maven.apache.org/maven2)] -> [幫助1]

這是您在這里的錯誤。 但是,如果在此搜索過程中進行了匹配,則Maven可以推斷出要使用的<artifactId>

現在,這意味着它具有組ID和工件ID。 最后一個難題是版本

將使用哪個版本?

除非在POM中明確配置,否則Maven將采用最新的版本(請參閱下一節)。 通過獲取另一個元數據文件(仍稱為maven-metadata.xml來檢索所有可能的版本,但這一次位於存儲庫中的工件ID文件夾旁邊(與上面的文件夾ID和組ID相反)。 以Maven Clean插件為例(可以通過上述機制和mvn clean:clean命令找到其組ID和工件ID), maven-metadata.xml如下所示:

<metadata>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-clean-plugin</artifactId>
  <versioning>
    <latest>3.0.0</latest>
    <release>3.0.0</release>
    <versions>
      <version>2.0-beta-1</version>
      <version>2.0-rc1</version>
      <version>2.0</version>
      <version>2.1</version>
      <!-- more versions -->
      <version>3.0.0</version>
    </versions>
    <lastUpdated>20151022205339</lastUpdated>
  </versioning>
</metadata>

Maven 將選擇 <release>版本作為版本 ,該版本代表插件的最新發行版本。 如果該標簽不存在,它將選擇<latest>代表插件,發行版或快照的最新版本。 可能會出現兩個標簽都不存在的情況,在這種情況下,Maven 將選擇 <version>元素列表的第一個版本或缺少版本的第一個快照

如果仍然失敗,則Maven無法為您做任何事情,無法推斷該版本,並且會出錯。 但這不太可能發生。 現在,我們收集了組ID,工件ID和版本。 是時候最終調用我們插件的bar目標了。

我的配置有什么問題?

如上所述,Maven在活動的遠程存儲庫中查找某些預定義的組ID,以查找具有給定前綴的匹配項。 用命令

mvn findbugs:findbugs

Maven使用findbugs前綴開始搜索。 由於我們的配置中的設置中沒有任何<pluginGroup> ,因此Maven會在org.codehaus.mojoorg.apache.maven.plugins組ID中查找前綴匹配項。

它確實找到了一個: Findbugs Maven插件發布在org.codehaus.mojo組ID下; 確實,您可以maven-metadata.xml找到它:

<plugin>
  <name>FindBugs Maven Plugin</name>
  <prefix>findbugs</prefix>
  <artifactId>findbugs-maven-plugin</artifactId>
</plugin>

您還可以通過偷看剛推導出的findbugs-maven-plugin下的maven-metadata.xml文件來找到要使用的版本(在撰寫本文時為3.0.4;並注意它與您的問題的mvn findbugs:findbugs日志中的版本)。 因此,解析成功了,然后Maven可以繼續調用此插件的findbugs目標。

第二個例子是命令

mvn jetty:run

和以前一樣,將執行相同的解析步驟,但是在這種情況下,您會發現前綴<jetty>不會出現在組ID org.codehaus.mojoorg.apache.maven.plugins任何maven-metadata.xmlorg.apache.maven.plugins 因此解決方案失敗,並且Maven返回您遇到的錯誤。

但是我們已經看到了如何使其工作! 我們可以在設置內添加<pluginGroup> ,以便在解析過程中也可以搜索該組ID。 Jetty Maven插件是在org.eclipse.jetty組下發布的,如果我們窺視Maven Central中相應的maven-metadata.xml ,您會看到<prefix>jetty</prefix>在那里。 因此解決方法很簡單:只需定義此新的組ID即可在設置中進行搜索:

<pluginGroups>
  <pluginGroup>org.eclipse.jetty</pluginGroup>
</pluginGroups>

現在,Maven還將調查此組ID,並將jetty前綴成功匹配到org.eclipse.jetty:jetty-maven-plugin

如何使用特定版本? 或者,我不想修改我的設置!

當然,如果您在POM中顯式定義了插件,那么所有這些解決方案都可以忽略不計,這是您找到的另一個解決方案:

<plugin>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>9.2.11.v20150529</version>
</plugin>

和使用

mvn jetty:run

如果您直接在POM中配置插件,則前綴解析仍然會發生,但是會有點掩蓋:Maven將從已配置的遠程存儲庫下載插件,並且將沿途下載並安裝所有元數據文件,包括maven-metadata.xml包含前綴jetty的映射。 因此,由於它會自動下載,因此搜索始終會成功。

還要注意,由於插件是在POM中定義的,因此您在設置中不需要任何<pluginGroup> :組ID是在POM中編寫的。 此外,它確保將使用版本9.2.11.v20150529,而不是最新版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM