当前位置: 首页 > 面试题库 >

Maven插件前缀解析如何工作?为什么要解决“ findbugs”而不是“ jetty”?

山越
2023-03-14
问题内容

我当时使用Maven进行了一些测试,意识到我可以执行findbugsFindbugs插件的目标,而无需将该插件添加到POM文件中。另一方面,当我需要运行runJetty插件的目标时,我被迫将插件添加到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

这将调用bar具有坐标my.plugin.groupId:foo-maven- plugin:1.0.0(以形式groupId:artifactId:version)的Foo
Maven插件的目标。它运作良好,但是有点冗长。不用指定所有这些坐标就可以以一种更简单的方式调用此目标,这将是很好的。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- plugingoalPrefix参数的帮助下自行配置。

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会寻找具有的前缀插件foo组id内org.mortbay.jettyorg.apache.maven.pluginsorg.codehaus.mojo

第二步是如何实际执行搜索。Maven maven-metadata.xml将从每个远程存储库中的组ID
下载元数据文件(如果已下载,则将其查找到本地存储库中)。如果以我们仅有的远程存储库为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旁边)。以Maven
Clean插件为例(其组ID和工件ID可通过上述机制和的命令找到mvn clean:clean),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>

您还可以通过maven- metadata.xmlfindbugs-maven-plugin刚推导出的文件(在撰写本文时为3.0.4;并注意mvn findbugs:findbugs问题日志中的版本与该版本完全匹配)下浏览该文件来找到要使用的版本。因此解析成功,然后Maven可以继续调用findbugs此插件的目标。

第二个例子是命令

mvn jetty:run

与以前一样,执行相同的解析步骤,但是在这种情况下,您会发现前缀在组ID
和的<jetty>任何中均未出现。因此解决方案失败,并且Maven返回您所具有的错误。maven- metadata.xml``org.codehaus.mojo``org.apache.maven.plugins

但是,我们已经看到了如何使其工作!我们可以<pluginGroup>在设置中添加一个内部,以便在解析过程中也可以搜索该组ID。该码头Maven插件是组ID下发布org.eclipse.jetty的,如果我们窥视到相应maven- metadata.xml的Maven的中央,你会发现<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,而不是最新版本。



 类似资料:
  • 我正在阅读这些文档,仍然不知道Maven是如何决定下载哪些版本的插件的。 例如,考虑以下简单场景: 一个空的本地存储库 默认settings.xml 运行一个简单的maven命令。例如,用于,如Maven在5分钟文档中所述。 运行命令后,Maven做的第一件事就是下载一堆插件。 Maven正在下载的一些插件包括: maven-clean-plugin-2.4.1 maven-install-plu

  • 我正在尝试让Gradle Artifactory插件来解析工件。 我的build.gradle文件在下面,被替换为正确的主机名 然而,当运行此命令时,它无法解析工件。依赖行是从artiFactory生成的。 我打算使用“旧”发布机制。我的Gradle版本是2.0。 我尝试了一个带有maven2默认值和gradle布局的artifactory存储库。 堆栈跟踪可在以下位置找到:http://text

  • 问题内容: 是的,这个问题相当冗长-抱歉。我保持尽可能的密集。我加粗了问题,以便在阅读整本书之前更容易窥视。 为什么Sax解析比dom解析快? 我唯一能想到的是,使用w / sax可能会忽略大多数传入的数据,因此不会浪费时间处理您不在乎的xml部分。IOW- 使用wx解析后,您无法重新创建原始输入。 如果您编写了SAX解析器,以便它考虑到每个xml节点(从而可以重新创建原始XML解析器),那么它不

  • 每当我在IntelliJ中创建一个新的Maven项目时,我总是得到这些错误。 无法解析插件org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M3 无法解析插件org.apache.maven.plugins:maven-install-plugin:3.0.0-M1 我的日志文件

  • 遵循一些maven docker示例,产生了以下代码,运行mvn包dockerfile:build,但出现以下错误:[错误]在当前项目和插件组[org.apache.maven.plugins,org.codehaus.mojo]中找不到前缀为“dockerfile”的插件,这些插件组可从存储库获得。。。 请问我该从这里去哪里?

  • 问题内容: 什么是空指针异常,什么原因导致它们? 可以使用哪些方法/工具确定原因,以阻止异常导致程序过早终止? 问题答案: 声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑以下代码,在其中声明基本类型的变量int: 在此示例中,变量是an ,Java会0为你初始化它。当你10在第二行为其分配值时,你的值将写入所指的存储位置x。 但是,当你尝试声明引用类型时,会发生一些不同的事情。采取以