Apache Maven — основы
После публикации топика о Maven в комментариях возникли вопросы о том, как начать с ним работать, с чего начать, как составлять файлы pom.xml, откуда брать плагины и т.п. Данный топик будет своего рода getting started или f.a.q.
Терминология
Как в любой системе, в Maven, есть свой набор терминов и понятий.
Вся структура проекта описывается в файле pom.xml (POM – Project Object Model), который должен находиться в корневой папке проекта. Ключевым понятием Maven является артефакт — это, по сути, любая библиотека, хранящаяся в репозитории. Это может быть какая-то зависимость или плагин.
Зависимости — это те библиотеки, которые непосредственно используются в вашем проекте для компиляции кода или его тестирования.
Плагины же используются самим Maven’ом при сборке проекта или для каких-то других целей (деплоймент, создание файлов проекта для Eclipse и др.).
В самом начале работы с Maven, пользователь непременно столкнется с таким понятием как архетип. Архетип — это некая стандартная компоновка файлов и каталогов в проектах различного рода (веб, swing-проекты и прочие). Другими словами, Maven знает, как обычно строятся проекты и в соответствии с архетипом создает структуру каталогов.
Как правило, название артефакта состоит из названия группы, собственного названия и версии. К примеру Spring будет иметь вот такое название в среде Maven: org.springframework.spring:2.5.5. Последний домен означает всегда artifactId, все, что перед ним – groupId – хорошо это запомните!
На жизненном цикле останавливаться не буду, так как он хорошо описан в вышеобозначенной статье. А теперь перейдем к практике.
Установка Maven
Последнюю версию всегда можно скачать на странице загрузки на официальном сайте. Просто распаковываем архив в любую директорию. Далее необходимо создать переменную в Path, в которой необходимо указать путь к Maven. Заходим в Win + Pause – Дополнительно – Переменные среды – в верхнем окошке нажимаем Создать, вводим имя M2_HOME и значение допустим “C:\apache-maven-2.2.1”. Далее там же создаем еще одну переменную M2 со значением %M2_HOME%\bin. Так же убеждаемся, что есть переменная JAVA_HOME с путем к JDK. Ее значение должно быть примерно таким «c:\Program Files\Java\jdk1.6.0_10\». И наконец в том же окошке создаем/модифицируем переменную Path, в нее необходимо просто написать %M2%, чтобы наша папочка с исполняемым файлом Maven была видна из командной строки. Теперь необходимо проверить работоспособность нашей установки. Для этого заходим в командную строку и вводим команду
mvn –version
Должна появиться информация о версиях Maven, jre и операционной системе, что-то вроде:
Maven version: 2.2.1 Java version: 1.6.0_10 OS name: "windows 2003" version: "5.2" arch: "x86" Family: "windows"
Maven создаст вам локальный репозиторий в вашей личной папке, например в каталоге C:\Documents and Settings\username\.m2\repository
Все, Maven готов к работе, можно приступать к созданию приложения.
Создание приложения из архетипа
На сайте Maven перечислены наиболее популярные архетипы для приложений, но вы можете легко создать свой или найти более специфичный например здесь.
Итак, допустим нас интересует веб-приложение – находим подходящий архетип, называется он maven-archetype-webapp. В командной строке, в необходимом каталоге выполняем команду Maven:
mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-webapp -DarchetypeArtifactId=maven-archetype-webapp
Теперь мы можем лицезреть довольно наглядную структуру каталогов с говорящими названиями java – здесь будут ваши классы, webapp – здесь размещаются странички веб-приложения, resources – различного рода ресурсы в classpath (файлы конфигурации, например), test – юнит-тесты, соответственно и т.п.
Сборка проекта
Здесь все просто – выполняем команду
mvn package
mvn install
в корневом каталоге приложения, там, где находится файл pom.xml. Первая команда скомпилирует ваш проект и поместит его в папку target, а вторая еще и положит его к вам в локальный репозиторий.
Есть полезная функция, наподобие конвеера, то есть можно написать
mvn clean install
и Maven сначала очистит папку target проекта, потом соберет его и положит в репозиторий.
Минимальный набор действий для работы Maven мы изучили, теперь переходим к кастомизации и добавлению зависимостей проекта.
Зависимости и репозитории
Как правило, большинство популярных библиотек находятся в центральном репозитории, поэтому их можно прописывать сразу в раздел dependencies вашего pom-файла. Например чтобы подключить Spring Framework необходимо определить следующую зависимость:
. org.springframework spring 2.5.5
Версию хотя и можно не указывать и тогда Maven возьмет последний вариант, но я вам лично советую это делать, потому как у нас неоднократно бывали случаи, что проект просто в один момент переставал собираться или начинал падать в совершенно неожиданных и хорошо оттестированных местах, хотя вроде бы никто ничего не менял.
Специфические вещи обычно не находятся в центральном репозитории и тогда вам придется указать репозиторий производителя вручную. Для примера добавим зависимость JSF-фреймворка ajax-компонентов JBoss RichFaces.
С зависимостями все просто:
org.richfaces.ui richfaces-ui 3.3.1.GA
А вот репозиторий JBoss теперь необходимо прописать ручками либо в файле settings.xml, который лежит в корне вашего локального репозитория, либо в самом файле pom.xml, в зависимости от того, нужен ли данный репозиторий во всех проектах, либо в каком-то одном конкретном, соответственно:
true false never repository.jboss.com Jboss Repository for Maven http://repository.jboss.com/maven2/ default
Как правило на сайтах крупных проектов пишут всю информацию, необходимую для встраивания их библиотеки в проект на основе Maven, но бывают случаи, когда артефакт приходится искать очень и очень долго. Здесь нам очень сильно может помочь MVNrepository.com — он вам всегда подскажет где может находиться искомая библиотечка. Но если уж и там не нашлось, то из собственного опыта могу посоветовать гуглить « pom.xml». Бывает так, что проекты уже давно закрыты и в репозитории не положены потому что разработчики уже не заботятся об их распространении. Тогда остается один единственный способ – добавить файл в репозиторий вручную командой:
mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversion= -Dpackaging=
Последний параметр чаще всего имеет значение jar.
Плагины
Так как плагины являются такими же артефактами, как и зависимости, то они описываются практически так же. Вместо раздела dependencies – plugins, dependency – plugin, repositories – pluginRepositories, repository – pluginRepository.
Плагинами Maven делает все, даже непосредственно то, для чего он затевался – сборку проекта, только этот плагин необязательно указывать в свойствах проекта, если вы не хотите добавить какие-то фичи.
Посмотрим как настроить плагин для создания проекта для Eclipse с использованием WTP ver. 2.0. В раздел plugins нашего pom.xml прописываем следующий плагин:
org.apache.maven.plugins maven-eclipse-plugin 2.0
Теперь идем опять таки в командную строку и выполняем команду
mvn eclipse:eclipse
Ждем пока Maven найдет все библиотеки в репозитории или скачает их и вуаля – теперь наш Maven-проект можно открыть как проект eclipse. При этом библиотеки никуда не копируются как при классическом подходе, а остаются в репозитории и Eclipse делает на них ссылку через свои переменные.
Единого списка всех плагинов естественно не существует, на официальном сайте только есть поддерживаемые плагины непосредственно разработчиками Maven. Однако хотелось бы отметить, что названия плагинов довольно прямолинейны и сделав поиск по ключевым словам «maven tomcat plugin» вы скорее всего обнаружите первой ссылкой плагин для деплоймента проекта в Tomcat.
Собственный репозиторий
К сожалению сам не имею большого опыта настройки репозитория, но могу посоветовать как наиболее простой и распространенный Nexus. За дополнительной информацией следует обратиться на сайт данного проекта.
Однако нельзя оставить без внимания и достойных конкурентов в лице Artifactory и Archiva.
Заключение
Очень надеюсь, что цель данной статьи достигнута – минимальных знаний по Maven должно хватить на работу с не очень большими проектами. Для более серьезных целей очень советую детально изучить maven-compiler-plugin и maven-resource-plugin – они напрямую отвечают за конечную компоновку проекта. Я считаю, что самым главным моментом в обучении Maven является понимание идеологии – Maven описывает конечную структуру проекта, а не пути к ее достижению, в отличие от Ant.
Полезные ссылки
Официальная страница Maven
Документация
Центральный репозиторий
Репозиторий iBiblio
Поиск артефактов по названию
Неплохой форум по Maven
Maven: The Definitive Guide — хорошая книга по Maven
Руководство по Maven. Жизненный цикл сборки.
Жизненный цикл сборки в Maven – это чётко определённая последовательность фаз во время выполнения которых должны быть достигнуты определённые цели.
Типичный жизненный цикл сборки Maven выглядит следующим образом:
Фаза | Действия | Описание |
---|---|---|
prepare-resources | Копирование ресурсов | В этой фазе происходит копирование ресурсов, которое, также, может быть настроено. |
compile | Компиляция | В этой фазе происходит компиляция исходного кода. |
package | Создание пакета | В этой фазе, в зависимости от настроек создаётся архив JAR/WAR. Тип архива указывается в pom.xml файле. |
install | Установка | В этой фазе происходит установка пакета в локальный/удалённый репозиторий maven. |
Каждая из этих фаз имеет фазы pre и post. Они могут быть использованы для регистрации задач, которые должны быть запущены перед и после указанной фазы.
Когда Maven начинает сборку проекта, он проходит через определённую последовательность фаз и выполняет определённые задачи, которые указаны в каждой из фаз. Maven имеет следующие 3 стандартных жизненных цикла:
Задача (goal) – это специальная задача, которая относится к сборке проекта и его управлению. Она может привязываться как к нескольким фазам, так и ни к одной. Задача, которая не привязана ни к одной фазе, может быть запущена вне фаз сборки с помощью прямого вызова.
Порядок выполнения зависит от порядка вызова целей и фаз.
Например, рассмотрим команду ниже. Аргументы clean и package являются фазами сборки до тех пор, пока dependency: copy-dependencies является задачей.
mvn clean dependency:copy-dependencies package
В этом случае, сначала будет выполнена фаза clean, после этого будет выполнена задача dependency: copy-dependencies. После чего будет выполнена фаза package.
Жизенный цикл Clean
Когда вы выполняете команду
mvn post-clean
Задача clean Maven (clean:clean) привязывается к фазе clean в жизненном цикле сборки. Эта задача удаляет ввод сборки путём удаления директории сборки. Таким образом, когда выполняется команда mvn clean, Maven удаляет директорию сборки.
Мы можем настроить это поведение указав эти задачи в любой из фаз сборки.
Рассмотрим пример, в котором мы привяжем задачу maven-antrun-plugin:run к фазам pre-clean, clean и post-clean.
4.0.0 ProselyteTutorials MavenTutorial 1.0-SNAPSHOT org.apache.maven.plugins maven-antrun-plugin 1.1 id.pre-clean pre-clean run pre-clean phase id.clean clean run clean phase id.post-clean post-clean run post-clean phase
После этого выполним в терминале следующую команду:
mvn post-clean
В результате мы получим следующий результат:
[INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MavenTutorial --- [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.clean) @ MavenTutorial --- [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.post-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] post-clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.417s [INFO] Finished at: Sun Mar 27 21:38:15 EEST 2016 [INFO] Final Memory: 7M/150M [INFO] ------------------------------------------------------------------------
Мы также можем выполнить такие же действия для фаз pre-clean и clean.
Жизненный цикл Default (Build)
Это основной жизненный цикл Maven, который используется для сборки проектов. Он включает в себя 23 фазы:
Фаза жизненного цикла | Описание |
---|---|
validate | Подтверждает, является ли проект корректным и вся ли необходимая информация доступа для завершения процесса сборки. |
initialize | Инициализирует состояние сборки, например, различные настройки. |
generate-sources | Включает любой исходный код в фазу компиляции. |
process-sources | Обрабатывает исходный код (подготавливает). Например, фильтрует определённые значения. |
generate-resources | Генерирует ресурсы, которые должны быть включены в пакет. |
process-resources | Копирует и отправляет ресурсы в указанную директорию. Это фаза перед упаковкой. |
compile | Комплирует исходный код проекта. |
process-classes | Обработка файлов, полученных в результате компиляции. Например, оптимизация байт-кода Java классов. |
generate-test-sources | Генерирует любые тестовые ресурсы, которые должны быть включены в фазу компиляции. |
process-test-sources | Обрабатывает исходный код тестов. Например, фильтрует значения. |
test-compile | Компилирует исходный код тестов в указанную директорию тестов. |
process-test-classes | Обрабатывает файлы, полученные в результате компиляции исходного кода тестов. |
test | Запускает тесты, используя приемлемый фреймворк юнит-тестирования (например, Junit). |
prepare-package | Выполняет все необходимые операции для подготовки пакет, непосредственно перед упаковкой. |
package | Преобразует скомпилированный код и пакет в дистрибутивный формат. Такие как JAR, WAR или EAR. |
pre-integration-test | Выполняет необходимые действия перед выполнением интеграционных тестов. |
integration-test | Обрабатывает и распаковывает пакет, если необходимо, в среду, где будут выполняться интеграционные тесты. |
post-integration-test | Выполняет действия, необходимые после выполнения интеграционных тестов. Например, освобождение ресурсов. |
verify | Выполняет любые проверки для подтверждения того, что пакет пригоден и отвечает критериям качества. |
install | Устанавливает пакет в локальный репозиторий, который может быть использован как зависимость в других локальных проектах. |
deploy | Копирует финальный пакет (архив) в удалённый репозиторий для, того, чтобы сделать его доступным другим разработчикам и проектам. |
Необходимо уточнить два момента:
- Когда мы выполняем команду Maven, например install, то будут выполнены фазы до install и фаза install.
- Различные задачи Maven будут привязаны к различным фазам жизненного цикла Maven в зависимости от типа архива (JAR/WAR/EAR).
В следующем примере, мы привязываем задачу maven-antrun-plugin:run к нескольким фазам жизненного цикла сборки. Это также позволяет нам вызывать текстовые сообщения, отображая фазу жизненного цикла.
4.0.0 ProselyteTutorials MavenTutorial 1.0-SNAPSHOT org.apache.maven.plugins maven-antrun-plugin 1.1 id.validate validate run validate phase id.compile compile run compile phase id.test test run test phase id.package package run package phase id.deploy deploy run deploy phase
После этого выполним следующую команду:
mvn compile
В результате мы получим, примерно, следующий результат:
[INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MavenTutorial --- [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.clean) @ MavenTutorial --- [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.post-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] post-clean phase [INFO] Executed tasks proselyte@proselyte:~/Programming/Projects/Proselyte/MavenTutorial$ mvn pre-clean [INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.331s [INFO] Finished at: Sun Mar 27 21:39:39 EEST 2016 [INFO] Final Memory: 7M/150M [INFO] ------------------------------------------------------------------------ proselyte@proselyte:~/Programming/Projects/Proselyte/MavenTutorial$ mvn clean [INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MavenTutorial --- [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.clean) @ MavenTutorial --- [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.405s [INFO] Finished at: Sun Mar 27 21:39:45 EEST 2016 [INFO] Final Memory: 6M/119M [INFO] ------------------------------------------------------------------------ proselyte@proselyte:~/Programming/Projects/Proselyte/MavenTutorial$ mvn post-clean [INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ MavenTutorial --- [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.clean) @ MavenTutorial --- [INFO] Executing tasks [echo] clean phase [INFO] Executed tasks [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.post-clean) @ MavenTutorial --- [INFO] Executing tasks [echo] post-clean phase [INFO] Executed tasks proselyte@proselyte:~/Programming/Projects/Proselyte/MavenTutorial$ mvn compile [INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.validate) @ MavenTutorial --- [INFO] Executing tasks [echo] validate phase [INFO] Executed tasks [INFO] [INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ MavenTutorial --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:2.0.2:compile (default-compile) @ MavenTutorial --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.compile) @ MavenTutorial --- [INFO] Executing tasks [echo] compile phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.824s [INFO] Finished at: Sun Mar 27 22:07:37 EEST 2016 [INFO] Final Memory: 8M/150M [INFO] ------------------------------------------------------------------------
Жизненный цикл Site
Плагин Maven – Site – используется для создания докладов, документации, развёртывания и т.д.
Он включает в себя такие фазы:
В примере ниже мы прикрепляем задачу maven-antrun-plugin:run ко всем фазам жизненного цикла Site. Это позволяет нам вызывать текстовые сообщения для отображения фаз жизненного цикла.
4.0.0 ProselyteTutorials MavenTutorial 1.0-SNAPSHOT org.apache.maven.plugins maven-antrun-plugin 1.1 id.pre-site pre-site run pre-site phase id.site site run site phase id.post-site post-site run post-site phase id.site-deploy site-deploy run site-deploy phase
Теперь выполним команду Maven:
mvn site
В результате мы получим, примерно, следующий результат:
[INFO] Scanning for projects. [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building MavenTutorial 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.pre-site) @ MavenTutorial --- [INFO] Executing tasks [echo] pre-site phase [INFO] Executed tasks [INFO] [INFO] --- maven-site-plugin:3.0:site (default-site) @ MavenTutorial --- [WARNING] Report plugin org.apache.maven.plugins:maven-project-info-reports-plugin has an empty version. [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [INFO] configuring report plugin org.apache.maven.plugins:maven-project-info-reports-plugin:2.9 [WARNING] No project URL defined - decoration links will not be relativized! [INFO] Rendering site with org.apache.maven.skins:maven-default-skin:jar:1.0 skin. [INFO] Generating "Dependency Convergence" report --- maven-project-info-reports-plugin:2.9 [INFO] Generating "Dependency Information" report --- maven-project-info-reports-plugin:2.9 [INFO] Generating "About" report --- maven-project-info-reports-plugin:2.9 [INFO] Generating "Plugin Management" report --- maven-project-info-reports-plugin:2.9 [INFO] Generating "Plugins" report --- maven-project-info-reports-plugin:2.9 [INFO] Generating "Summary" report --- maven-project-info-reports-plugin:2.9 [INFO] [INFO] --- maven-antrun-plugin:1.1:run (id.site) @ MavenTutorial --- [INFO] Executing tasks [echo] site phase [INFO] Executed tasks [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.717s [INFO] Finished at: Sun Mar 27 23:02:41 EEST 2016 [INFO] Final Memory: 17M/268M [INFO] ------------------------------------------------------------------------
В этом уроке мы изучили основы жизненного цикла сборки проектов в Maven.
В следующем уроке мы изучим профиль сборки.
Как ускорить сборку с Maven
Что делать, если сборка (build) с Maven проходит слишком медленно? Ведь когда сборка длится слишком долго, любой, даже самый терпеливый разработчик, может заскучать и отвлечься.
Для быстрого поиска в Google или для закладок, сразу предлагаю итоговое решение:
mvn package -am -o -Dmaven.test.skip -T 1C
— для сборки проекта без тестов.
Эта история началась с того, что я выкачал довольно большой проект на Java из нашего корпоративного репозитория. Думаю, что многие, как и я, сразу собрали бы его командой:
mvn clean package
, ну а многие командой:
mvn clean install
Мой проект собрался за 25 минут, и каждый раз собирался так же долго, как и в первый раз.
package вместо install
Согласно жизненному циклу сборки проекта после фазы package, на которой мы получаем полноценный jar-файл, есть фаза verify, а затем install. Часто необходимо получить именно jar-файл, который нет необходимости помещать в локальный репозиторий, поэтому в данной ситуации я остановился на package и сэкономил немного времени.
Параллельная сборка
При обычном запуске Maven не использует все возможности современных процессоров по распараллеливанию вычислений на разных ядрах, собирая модули один за другим. К счастью, можно воспользоваться параметром -T, указав Maven, что необходимо построить граф зависимостей и собирать модули параллельно.
Параметром можно воспользоваться разными способами:
mvn -T 4 package
mvn -T 1C package
В первом случае вы указываете число потоков для использования Maven, а во втором — что необходимо использовать один поток на каждое ядро CPU.
Второй способ задания параметра, привязанный к количеству ядер, я и собираюсь использовать в своей итоговой команде.
Поэкспериментировав с количеством потоков на ядро, попробовав следующие варианты:
mvn -T 1C package mvn -T 1.5C package mvn -T 2C package
- Surefire с параметром forkMode=never, surefire [2.6,) предупреждает (assert) об этом.
- maven-modello-plugin, исправлено с версии 1.4,
- Все клиенты maven-archiver (EAR, EJB, JAR, WAR etc), исправлено в последних версиях
- plexus-utils 2.0.5
- maven-archiver 2.4.1
- plexus-archiver 1.0
- plexus-io 1.0
Инкрементальная сборка
Как мы обсуждали выше, проект чаще всего собирается командой:
mvn clean package
Команда clean используется для очистки проекта, но так ли это нужно каждый раз при сборке? Нет, обычно мы хотим инкрементального обновления проекта, и Maven на это способен при помощи команды:
mvn package -am
Maven собирает модуль и обновляет те модули, от которых зависит данный модуль, в случае если в них что-то поменялось.
Эта опция в разы ускоряет сборку проектов из многих модулей, в которых, как правило, вносятся точечные изменения в 1-2 модуля.
Оффлайновая сборка
Часто бывает так, что артефакты на внешних репозиториях обновляются не так уж и часто, особенно, когда это артефакты определённой версии, или эти артефакты должны поддерживаться вашими усилиями (- Добро пожаловать в новый проект!). Довольно логично в такой ситуации сообщить Maven, что не нужно каждый раз заново скачивать их из репозиториев:
mvn package -o
mvn package --offline
Мы для лаконичности остановимся на первом варианте.
Пропуск тестов
Пожалуй, самое спорное предложение по оптимизации скорости сборки я оставил напоследок. Тем, кто полностью разделяет ценности TDD, я просто предлагаю пролистнуть этот абзац и убрать из нашей итоговой команды параметр -Dmaven.test.skip.
Не буду отрицать, тесты, безусловно, нужны, и программист должен понимать ту часть ответственности, которую он берёт на себя, отключая их. Но если вы вдруг столкнулись с новым гигантским проектом, в котором кто-то когда-то написал тесты, и они не работают, то вам и так придётся их для начала отключить.
Что касается опции запуска Maven, я хочу отметить только то, что, как правило, для того, чтобы пропустить тесты пользуются командой:
mvn package -DskipTests
Но при этом можно также пропустить компиляцию тестов, если выполнить команду в следующем виде:
mvn package -Dmaven.test.skip
Подведём итоги
Итак, ещё раз команда, которая получилась у нас для ускорения сборки с Maven:
mvn package -am -o -Dmaven.test.skip -T 1C
Результат, показанный на собираемом мной проекте, радует: сборка вместо 25 минут стала проходить за 30 секунд.
Авторы некоторых других статей по оптимизации скорости сборки с Maven также рекомендуют использовать параметры оптимизации запуска компилятора:
MAVEN_OPTS= -XX:+TieredCompilation -XX:TieredStopAtLevel=1 mvn package
— но, во-первых, я не почувствовал какого-то реального ускорения сборки, по всей видимости, из-за того, что я и так пользовался инкрементальной сборкой и процесс компиляции отнимал в этом случае не так много времени, а во-вторых, встречается достаточное количество упоминаний того, что эти параметры могут вызвать ошибки OutOfMemory и прочие проблемы.
Надеюсь, что в комментариях вы также поделитесь статистикой по ускорению сборки ваших проектов!
Часть 4. Основы Maven
Этот материал — часть цикла “Введение в Enterprise-разработку”. Предыдущие статьи:
- о сети;
- об архитектуре ПО;
- о протоколах HTTP/HTTPS.
Maven — инструмент для управления и сборки проектов — настоящий помощник Java-программиста. Он облегчает жизнь девелоперу на всех стадиях работы: от создания структуры проекта и подключения необходимых библиотек до развертывания продукта на сервере. При работе с любым фреймворком придется использовать Maven. Поэтому давай сегодня разберем его основные функции и посмотрим, как их нужно использовать.
Пошаговая установка Maven
- Для начала нужно установить Maven, скачав его по этой ссылке.
- Далее необходимо распаковать скачанный архив и установить переменной окружения M2_HOME ссылку на местонахождение распакованного архива. Например, C:\Program Files\maven\
- Чтобы проверить, что все установилось, в командной строке пропиши: mvn -version
- Если отобразится информация о версии Maven, Java и т.д., все готово к работе.
- Теперь открой IntelliJIDEA и создай новый проект. В первом же окне выбери Maven:
- Нажми Next и заполни следующее диалоговое окно:
- Далее стандартно создай проект в необходимом месте. После того, как проект создался, обрати внимание на его структуру:
Это cтандартная структура для Maven-проекта :
- в папке src/main/java содержатся java-классы;
- в src/main/resources — ресурсы, которые использует наше приложение (HTML-страницы, картинки, таблицы стилей и тд);
- src/test — для тестов.
Еще обрати внимание на файл под название pom.xml . Это и есть главный файл для управления Мавеном . Все описание проекта содержится здесь. Пока там не слишком много информации, но сейчас мы будем ее добавлять.
Управление зависимостями в Maven
Возможно, ты встречал словосочетание “менеджер зависимостей” или “dependency manager”. Мавен все это умеет. Благодаря Мавену тебе не нужно тратить кучу времени на поиски нужной библиотеки в интернете, качать ее, а потом подключать к проекту: достаточно добавить необходимую в список зависимостей Мавена. Зависимости записываются в XML-ноду dependencies Скажем, тебе в проекте нужна библиотека Apache Commons IO для упрощенной работы с файлами. Чтобы добавить библиотеку, напиши пять строк в pom.xml:
commons-io commons-io 2.6
Теперь твой pom.xml должен выглядеть так:
4.0.0 example.com example 1.0-SNAPSHOT commons-io commons-io 2.6
После этого разреши IntelliJ IDEA импортировать зависимость (диалоговое окно должно появиться в правом нижнем углу). Теперь библиотека готова к использованию:
import org.apache.commons.io.FileUtils; import java.io.File; public class TestMaven < public static void main(String[] args) < File tempDirectory = FileUtils.getTempDirectory(); >>
- На сайте библиотеки. Если нам нужен Apache Commons IO, переходим на официальный сайт, выбираем вкладку Dependency Information. Здесь есть вся необходимая информация — ее можно просто скопировать и добавить в наш раздел dependencies.
- В Maven-репозитории. В поиске введи “apache commons io”, и ты увидишь все доступные версии библиотеки. После выбора нужной, просто скопируй:
commons-io commons-io 2.6
Виды Maven-репозиториев
Стоит еще раз упомянуть Мавен-репозиторий, потому что их на самом деле у нас два — внешний (глобальный) и локальный, у тебя на компьютере. Все библиотеки, которые ты добавляешь в свои проекты, сохраняются в локальном репозитории. Когда Maven добавляет необходимую зависимость в проект, он сначала проверяет локальный репозиторий на наличие такой библиотеки, и только если не находит ее там — обращается к внешнему. Как видишь, можно использовать Мавен для добавления зависимостей, но это не все, что он умеет делать.
Сборка Java-проекта с помощью Maven
Возможно, новичку эта возможность покажется бессмысленной. Зачем это нужно, если есть IDE? Но нет! Во-первых, на сервере, на котором придется собирать приложение, может не быть не то что среды разработки, но и графического интерфейса. Во-вторых, на больших проектах Мавен лучше справляется с задачами по сборке проекта. Поэтому не будем томить себя ожиданием, а рассмотрим процесс сборки приложения с использованием Maven.
Фазы
Процесс построения приложения называют жизненным циклом Maven-проекта, и состоит он из фаз (phase). Посмотреть на них ты можешь в IDEA, нажав на Maven>example>Lifecycle в правом верхнем углу: Как видишь, существует 9 фаз:
- clean — удаляются все скомпилированные файлы из каталога target (место, в котором сохраняются готовые артефакты);
- validate — идет проверка, вся ли информация доступна для сборки проекта;
- compile — компилируются файлы с исходным кодом;
- test — запускаются тесты;
- package — упаковываются скомпилированные файлы (в jar, war и т.д. архив);
- verify — выполняются проверки для подтверждения готовности упакованного файла;
- install — пакет помещается в локальный репозиторий. Теперь он может использоваться другими проектами как внешняя библиотека;
- site — создается документация проекта;
- deploy — собранный архив копируется в удаленный репозиторий.
Все фазы выполняются последовательно: нельзя запустить, скажем, четвертую фазы, пока не завершены фазы 1-3. Выполнить запуск фазы можно двумя способами:
- через командную строку: mvn package
- используя Intellij IDEA: До запуска package выполняются фазы validate, compile, test. Исключение — фаза clean. Ее желательно вызывать перед каждой новой сборкой проекта. Фазы можно перечислить через пробел: mvn clean package.
Также у каждой фазы есть пре- и пост-фазы: например, pre-deploy, post-deploy, pre-clean, post-clean, но используются они довольно редко. Кроме этого, у каждой фазы есть цели (goal). Стандартные цели заложены по умолчанию, дополнительные добавляются Maven-плагинами. Иногда во время какой-то фазы нужно выполнить дополнительный функционал. Для этого существуют Maven-плагины. Список официальных плагинов можно посмотреть на сайте Мавена. Но знай, что еще есть много пользовательских плагинов, которые можно найти на сторонних ресурсах. Ну и естественно, при какой-то экзотической необходимости, у тебя всегда остается возможность написать такой плагин самому .
Плагины
Чтобы добавить Мавен-плагин в проект, его описание, аналогично зависимостям, нужно поместить в pom.xml в тег
4.0.0 example.com example 1.0-SNAPSHOT com.soebes.maven.plugins uptodate-maven-plugin 0.2.0 dependency validate commons-io commons-io 2.6
Мы все так же можем продолжать работу над нашим проектом. Но давай попробуем поменять версию Apache Commons IO на 2.0 и запустить сборку проекта. Получим: [ERROR] Failed to execute goal com.soebes.maven.plugins:uptodate-maven-plugin:0.2.0:dependency (default) on project example: There is a more up-to-date version ( 2.6 ) of the dependency commons-io:commons-io:2.0 available. -> [Help 1] Здесь у нас ошибка сборки, вызванная плагином. В сообщении к ошибке указано, что мы используем 2.0 версию при наличии 2.6. Вообще, Мавен очень полезный инструмент. Возможно, поначалу он покажется трудным в использовании, но практикуйся, создавай свои проекты под управлением Мавена, и через некоторое время ты будешь очень доволен результатом. В этой статье нарочно упущено много деталей о Мавене — мы сконцентрировались на самом необходимом. Но совершенству нет предела: почитать больше о Maven можно на официальном сайте продукта. Часть 5. Сервлеты. Пишем простое веб-приложение Часть 6. Контейнеры сервлетов Часть 7. Знакомство с паттерном MVC (Model-View-Controller) Часть 8. Пишем небольшое приложение на spring-boot