Как работает разрешение префикса плагина Maven? Почему это разрешает "findbugs", а не "причал"?
Я проводил тестирование с использованием Maven и понял, что могу выполнить findbugs
цель плагина Findbugs без добавления плагина в файл POM. С другой стороны, когда мне нужно было запустить run
цель плагина Jetty, я был вынужден добавить плагин в файл POM или сборка не удалась.
- Почему Jetty нужна была конфигурация в POM, а Findbugs - нет?
- Как Maven узнает, какие Findbugs нужно выполнить (предположим, что мы должны иметь плагины с тем же именем, но с другим идентификатором группы)?
Когда я запускаю первую команду, сборка успешна без каких-либо изменений в файле 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>
1 ответ
Что такое префикс и зачем он нам нужен?
Вы только что столкнулись с разрешением префикса плагина Maven. Это функция, которая позволяет пользователю вызывать цели определенного плагина Maven, используя его префикс. Когда вы напрямую вызываете цель в командной строке, вы можете использовать полнофункциональную форму:
mvn my.plugin.groupId:foo-maven-plugin:1.0.0:bar
Это будет ссылаться на цель bar
плагина Foo Maven с координатами my.plugin.groupId:foo-maven-plugin:1.0.0
(в виде groupId:artifactId:version
). Это работает хорошо, но это немного многословно. Было бы неплохо вызвать эту цель более простым способом, без указания всех этих координат. Maven делает это возможным, назначая префиксы плагинам, так что вы можете ссылаться на этот префикс вместо целых координат с помощью:
mvn foo:bar
^^^ ^^^
| |
prefix |
|
goal
Как определяется этот префикс?
Вы можете определить префикс для каждого плагина Maven. Это соответствует простому имени, используемому для его идентификации:
Обычные форматы идентификаторов артефактов:
maven-${prefix}-plugin
- для официальных плагинов, поддерживаемых самой командой Apache Maven (вы не должны использовать этот шаблон именования для своего плагина, см. эту заметку для получения дополнительной информации)${prefix}-maven-plugin
- для плагинов из других источниковЕсли artifactId вашего плагина соответствует этому шаблону, Maven автоматически сопоставит ваш плагин с правильным префиксом в метаданных, хранящихся в пути groupId вашего плагина в хранилище.
Другими словами, если идентификатор артефакта вашего плагина называется 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, какой идентификатор группы следует учитывать, когда вы используете префикс в команде. По умолчанию, в дополнение к группам, указанным в настройках, Maven также выполняет поиск идентификаторов групп. org.apache.maven.plugins
а также org.codehaus.mojo
, Он ищет те по умолчанию после тех, которые вы настроили в настройках. Поэтому с приведенной выше конфигурацией и командой mvn foo:bar
Maven будет искать плагин с префиксом foo
внутри идентификатора группы org.mortbay.jetty
, org.apache.maven.plugins
а также org.codehaus.mojo
,
Второй шаг - как этот поиск выполняется на самом деле. Maven загрузит файлы метаданных (или заглянет в ваш локальный репозиторий, если они уже загружены), называемый maven-metadata.xml
из каждого удаленного репозитория на эти идентификаторы группы. Если мы возьмем пример, где единственным удаленным репозиторием, который у нас есть, является Maven Central, Maven сначала загрузит http://repo1.maven.org/maven2/org/mortbay/jetty/maven-metadata.xml
и загляните внутрь этого файла, если у нас есть что-то отображающее foo
, Обратите внимание, как идентификатор группы был преобразован в структуру каталогов в удаленном хранилище. Структура этого файла метаданных:
<metadata>
<plugins>
<plugin>
<name>Some Awesome Maven Plugin</name>
<prefix>somePrefix</prefix>
<artifactId>some-maven-plugin</artifactId>
</plugin>
</plugins>
</metadata>
Если ни один из <plugin>
раздел содержит <prefix>
равный указанному нами (foo
), Maven продолжит работу с идентификатором следующей группы, нажав 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 больше ничего не сможет сделать для вас, и это приведет к ошибке:
[ОШИБКА] Плагин не найден для префикса 'foo' в текущем проекте и в группах плагинов [org.mortbay.jetty, org.apache.maven.plugins, org.codehaus.mojo], доступных в репозиториях [local (.../.m2/repository), центральная ( http://repo.maven.apache.org/maven2)] -> [Помощь 1]
Это ошибка у вас здесь. Однако, если во время этого поиска было найдено одно совпадение, Maven может вывести <artifactId>
использовать.
Теперь это означает, что у него есть идентификатор группы и идентификатор артефакта. Последний кусок головоломки - версия
Какая версия будет использоваться?
Maven возьмет последнюю доступную версию, если она явно не настроена в POM (см. Следующий раздел). Все возможные версии извлекаются путем извлечения другого файла метаданных, все еще называемого maven-metadata.xml
, но на этот раз он живет рядом с папкой с идентификатором артефакта в хранилище (в отличие от приведенных выше, где он был рядом с идентификатором группы). Взяв пример плагина Maven Clean (идентификатор группы и идентификатор артефакта которого можно найти с помощью вышеуказанного механизма и команды 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 больше ничего не может для вас сделать, версия не может быть выведена, и она содержит ошибки. Это вряд ли произойдет, хотя. Теперь мы собрали идентификатор группы, идентификатор артефакта и версию; время, наконец, призвать bar
цель нашего плагина.
В чем проблема с моей конфигурацией?
Как было сказано выше, Maven просматривает определенные заранее определенные групповые идентификаторы внутри активных удаленных репозиториев для поиска совпадений с заданным префиксом. С помощью команды
mvn findbugs:findbugs
Maven начинает поиск с findbugs
префикс. Поскольку в нашей конфигурации нет <pluginGroup>
в наших настройках Maven изучает org.codehaus.mojo
а также org.apache.maven.plugins
идентификатор группы для соответствия префикса.
И он действительно находит: плагин Findbugs Maven публикуется под org.codehaus.mojo
идентификатор группы; действительно, вы можете найти его в maven-metadata.xml
:
<plugin>
<name>FindBugs Maven Plugin</name>
<prefix>findbugs</prefix>
<artifactId>findbugs-maven-plugin</artifactId>
</plugin>
И вы также можете найти версию, которая будет использоваться, заглядывая в maven-metadata.xml
файл под findbugs-maven-plugin
только что вывел (3.0.4 на момент написания этой статьи; и обратите внимание, что он точно соответствует версии в mvn findbugs:findbugs
логи вашего вопроса). Таким образом, решение прошло успешно, и тогда Maven может продолжать вызывать findbugs
цель этого плагина.
Второй пример - команда
mvn jetty:run
Как и раньше, выполняются те же шаги разрешения, но в этом случае вы обнаружите, что префикс <jetty>
не появляется ни в одном из maven-metadata.xml
для групповых идентификаторов org.codehaus.mojo
а также org.apache.maven.plugins
, Таким образом, разрешение не удается, и Maven возвращает ошибку, которая у вас есть.
Но мы видели, как заставить это работать! Мы можем добавить <pluginGroup>
в наших настройках, так что этот идентификатор группы также можно искать во время разрешения. Плагин Jetty Maven публикуется под идентификатором группы org.eclipse.jetty
и если мы заглянем в соответствующий maven-metadata.xml
в Maven Central вы увидите, что <prefix>jetty</prefix>
есть. Так что исправить это просто: просто определите этот новый идентификатор группы для поиска в настройках:
<pluginGroups>
<pluginGroup>org.eclipse.jetty</pluginGroup>
</pluginGroups>
Теперь Maven также изучит этот идентификатор группы и сопоставит 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>
в настройках: идентификатор группы был написан в POM. Кроме того, он гарантирует, что будет использоваться версия 9.2.11.v20150529 вместо самой последней.