[英]How does Maven plugin prefix resolution work? Why is it resolving “findbugs” but not “jetty”?
我当时使用Maven进行了一些测试,意识到我可以执行Findbugs插件的findbugs
目标,而无需将该插件添加到POM文件中。 另一方面,当我需要运行Jetty插件的run
目标时,我被迫将插件添加到POM文件中,或者构建失败。
当我运行第一个命令时,构建成功,而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
参数的帮助下进行配置。
在命令中
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.plugins
和org.codehaus.mojo
。 它会在您在设置中配置的默认值之后搜索这些默认值。 因此,使用上述配置以及mvn foo:bar
的命令,Maven将在组ID org.mortbay.jetty
, org.apache.maven.plugins
和org.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.mojo
和org.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.mojo
和org.apache.maven.plugins
任何maven-metadata.xml
中org.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.