繁体   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