Maven插件前缀解析如何工作? 为什么它解决“findbugs”而不是“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文件中:
org.eclipse.jetty jetty-maven-plugin 9.2.11.v20150529
什么是前缀,我们为什么需要它?
您刚刚遇到了Maven的插件前缀解析 。 这是一个使用户能够通过使用其前缀来调用特定Maven插件的目标的function。 在命令行上直接调用目标时,可以使用function齐全的forms:
mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar
这将调用具有坐标my.plugin.groupId:foo-maven-plugin:1.0.0
(以groupId:artifactId:version
的forms)的Foo Maven插件的目标bar
。 它运作良好,但有点冗长。 如果不指定所有这些坐标,以更简单的方式调用此目标会很好。 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
文件中,您可以添加以下forms的插件组 :
org.mortbay.jetty
这样做,告诉Maven当你在命令中使用前缀时应该考虑哪个组ID。 默认情况下,除了设置中指定的组之外, Maven还会搜索组ids 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是如何转换为远程存储库中的目录结构的。 此元数据文件的结构是:
Some Awesome Maven Plugin somePrefix some-maven-plugin
如果
部分中没有一个
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’的插件,可从存储库[local(.. ./.m2/repository),central(http://repo.maven.apache.org/maven2) ] – > [帮助1]
这是你在这里的错误。 但是,如果在此搜索期间进行了一次匹配,则Maven可以推断出要使用的
。
它现在意味着它具有组ID和工件ID。 最后一块拼图是版本
将使用哪个版本?
除非在POM中明确配置,否则Maven将采用最新的一个(参见下一节)。 通过获取另一个元数据文件(仍然称为maven-metadata.xml
来检索所有可能的版本,但这次与存储库中的工件id文件夹一起生成(与上面的文件夹文件夹相反,它与组ID一起)。 以Maven Clean插件(其组ID和工件ID将通过上述机制和mvn clean:clean
命令找到)为例, maven-metadata.xml
如下所示:
org.apache.maven.plugins maven-clean-plugin 3.0.0 3.0.0 2.0-beta-1 2.0-rc1 2.0 2.1 3.0.0 20151022205339
Maven 将选择
版本作为版本 ,该版本代表插件的最新版本。 如果那个标签不存在,它将选择
,它代表插件,发行版或快照的最新版本。 可能会发生两个标签都不存在,在这种情况下,Maven 将选择
元素列表的第一个版本或缺少版本的第一个快照 。
如果仍然失败,那么Maven就无法再为您做什么,无法推断出版本并且错误。 但这不太可能发生。 我们现在收集了组ID,工件ID和版本; 是时候最终调用插件的目标了。
我的配置有什么问题?
如上所述,Maven查看活动远程存储库中的某些预定义组ID以查找具有给定前缀的匹配。 随着命令
mvn findbugs:findbugs
Maven使用findbugs
前缀开始搜索。 由于我们的配置在我们的设置中没有任何
,因此Maven会查找org.codehaus.mojo
和org.apache.maven.plugins
组ID以获得前缀匹配。
它确实找到了一个: Findbugs Maven插件是在org.codehaus.mojo
组id下发布的; 实际上,你可以在maven-metadata.xml
找到它:
FindBugs Maven Plugin findbugs findbugs-maven-plugin
您还可以通过findbugs-maven-plugin
刚刚推导出的findbugs-maven-plugin
下的maven-metadata.xml
文件找到将要使用的版本(在撰写本文时为3.0.4;并注意它是如何与mvn findbugs:findbugs
中的版本mvn findbugs:findbugs
你的问题的mvn findbugs:findbugs
日志)。 所以解决方案成功了,然后Maven可以继续调用这个插件的findbugs
目标。
第二个例子是命令
mvn jetty:run
和以前一样,会发生相同的解决步骤,但是,在这种情况下,您会发现前缀
没有出现在组ids org.codehaus.mojo
和org.apache.maven.plugins
任何maven-metadata.xml
中org.apache.maven.plugins
。 因此解决方案失败,Maven返回您所拥有的错误。
但我们已经看到了如何让它发挥作用! 我们可以在设置中添加
,以便在解析期间也可以搜索此组ID。 Jetty Maven插件是在组ID org.eclipse.jetty
下发布的,如果我们查看Maven Central中相应的maven-metadata.xml
,你会看到
org.eclipse.jetty
现在,Maven还将查看此组ID,并将jetty
前缀与org.eclipse.jetty:jetty-maven-plugin
成功匹配。
我该如何使用特定版本? 或者,我不想修改我的设置!
当然,如果您在POM中明确定义插件,则可以侧面跟踪所有此解决方案,这是您找到的另一个解决方案:
org.eclipse.jetty jetty-maven-plugin 9.2.11.v20150529
并使用
mvn jetty:run
如果您直接在POM中配置插件,前缀解析仍然会发生,但它有点掩盖:Maven将从配置的远程存储库下载插件,并将下载并安装所有元数据文件,包括maven-metadata.xml
包含前缀jetty
的映射。 因此,自动下载后,搜索始终成功。
另请注意,由于插件是在POM中定义的,因此设置中不需要任何
:组ID是在POM中编写的。 此外,它确保将使用版本9.2.11.v20150529,而不是最新版本。