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 была видна из командной строки. Теперь необходимо проверить работоспособность нашей установки. Для этого заходим в командную строку и вводим команду
Должна появиться информация о версиях Maven, jre и операционной системе, что-то вроде:
Maven создаст вам локальный репозиторий в вашей личной папке, например в каталоге C:\Documents and Settings\username\.m2\repository
Все, Maven готов к работе, можно приступать к созданию приложения.
Создание приложения из архетипа
На сайте Maven перечислены наиболее популярные архетипы для приложений, но вы можете легко создать свой или найти более специфичный например здесь.
Итак, допустим нас интересует веб-приложение – находим подходящий архетип, называется он maven-archetype-webapp. В командной строке, в необходимом каталоге выполняем команду Maven:
Теперь мы можем лицезреть довольно наглядную структуру каталогов с говорящими названиями java – здесь будут ваши классы, webapp – здесь размещаются странички веб-приложения, resources – различного рода ресурсы в classpath (файлы конфигурации, например), test – юнит-тесты, соответственно и т.п.
Сборка проекта
Здесь все просто – выполняем команду
в корневом каталоге приложения, там, где находится файл pom.xml. Первая команда скомпилирует ваш проект и поместит его в папку target, а вторая еще и положит его к вам в локальный репозиторий.
Есть полезная функция, наподобие конвеера, то есть можно написать
и Maven сначала очистит папку target проекта, потом соберет его и положит в репозиторий.
Минимальный набор действий для работы Maven мы изучили, теперь переходим к кастомизации и добавлению зависимостей проекта.
Зависимости и репозитории
Как правило, большинство популярных библиотек находятся в центральном репозитории, поэтому их можно прописывать сразу в раздел dependencies вашего pom-файла. Например чтобы подключить Spring Framework необходимо определить следующую зависимость:
Версию хотя и можно не указывать и тогда Maven возьмет последний вариант, но я вам лично советую это делать, потому как у нас неоднократно бывали случаи, что проект просто в один момент переставал собираться или начинал падать в совершенно неожиданных и хорошо оттестированных местах, хотя вроде бы никто ничего не менял.
Специфические вещи обычно не находятся в центральном репозитории и тогда вам придется указать репозиторий производителя вручную. Для примера добавим зависимость JSF-фреймворка ajax-компонентов JBoss RichFaces.
С зависимостями все просто:
А вот репозиторий JBoss теперь необходимо прописать ручками либо в файле settings.xml, который лежит в корне вашего локального репозитория, либо в самом файле pom.xml, в зависимости от того, нужен ли данный репозиторий во всех проектах, либо в каком-то одном конкретном, соответственно:
Как правило на сайтах крупных проектов пишут всю информацию, необходимую для встраивания их библиотеки в проект на основе Maven, но бывают случаи, когда артефакт приходится искать очень и очень долго. Здесь нам очень сильно может помочь MVNrepository.com — он вам всегда подскажет где может находиться искомая библиотечка. Но если уж и там не нашлось, то из собственного опыта могу посоветовать гуглить « pom.xml». Бывает так, что проекты уже давно закрыты и в репозитории не положены потому что разработчики уже не заботятся об их распространении. Тогда остается один единственный способ – добавить файл в репозиторий вручную командой:
Последний параметр чаще всего имеет значение jar.
Плагины
Так как плагины являются такими же артефактами, как и зависимости, то они описываются практически так же. Вместо раздела dependencies – plugins, dependency – plugin, repositories – pluginRepositories, repository – pluginRepository.
Плагинами Maven делает все, даже непосредственно то, для чего он затевался – сборку проекта, только этот плагин необязательно указывать в свойствах проекта, если вы не хотите добавить какие-то фичи.
Посмотрим как настроить плагин для создания проекта для Eclipse с использованием WTP ver. 2.0. В раздел plugins нашего pom.xml прописываем следующий плагин:
Теперь идем опять таки в командную строку и выполняем команду
Ждем пока Maven найдет все библиотеки в репозитории или скачает их и вуаля – теперь наш Maven-проект можно открыть как проект eclipse. При этом библиотеки никуда не копируются как при классическом подходе, а остаются в репозитории и Eclipse делает на них ссылку через свои переменные.
Единого списка всех плагинов естественно не существует, на официальном сайте только есть поддерживаемые плагины непосредственно разработчиками Maven. Однако хотелось бы отметить, что названия плагинов довольно прямолинейны и сделав поиск по ключевым словам «maven tomcat plugin» вы скорее всего обнаружите первой ссылкой плагин для деплоймента проекта в Tomcat.
Собственный репозиторий
К сожалению сам не имею большого опыта настройки репозитория, но могу посоветовать как наиболее простой и распространенный Nexus. За дополнительной информацией следует обратиться на сайт данного проекта.
Однако нельзя оставить без внимания и достойных конкурентов в лице Artifactory и Archiva.
Maven — зачем?
Это общая модель проектов. В ней описываются такие общие характеристики как имя, версия, авторы и их контактная информация, VCS проекта и вообще связанные с ним сетевые ресурсы, тип проекта (например библиотека или web-модуль, в оригинальной терминологии называется packaging, хотя влияет не только на тип получаемого артефакта), связи с другими проектами, используемые при сборке плагины и описания способа их задействования. Мне кажутся особенно важными два компонента этой модели.
Связи с другими модулями
POM допускает три типа связей с другими модулями: зависимость, включение и наследование.
Зависимость, эта связь говорит, что для некоторых фаз жизненного цикла нашего модуля, требуются некоторые артефакты модулей-зависимостей (абстрактно получилось — аж самому страшно). Что конкретно и на какой фазе жизненного цикла требуется определяется так называемой областью действия зависимости. Maven понимает несколько предопределённых областей действия и позволяет добавлять свои. В качестве примера ограничусь одной областью действия: compile — она говорит, что бинарные сборки зависимости требуются на этапе компиляции, выполнения тестов и во время выполнения.
Включение — говорит, что связанный модуль является неотъемлемой частью нашего модуля. Для прохождения нашим модулем некоторой фазы жизненного цикла, входящий в него также должен пройти эту фазу. Классический пример enterprise-модуль, включающий в себя web-модуль, пакет с EJB и общую библиотеку. Очевидно, что его сборка требует сборки каждого из включаемых модулей.
Наследование. Такая связь подразумевает перенос на наследника части модели предка. Правила переноса несколько запутаны, но в основном действует принцип — значение параметра модели предка становится умолчанием для модели потомка. Пример из моей практики: был создан модуль, устанавливающий версию JDK для компиляции проектов, внутренние репозитарии для результатов, набор правил для поверки соответствия исходников стандарту кодирования, он должен был использоваться (а кое-где и действительно использовался 😉 ) как родитель для всех разрабатываемых в рамках проекта модулей.
Описание используемых при сборке плагинов
Описание состоит из имени задействуемого плагина, некоторых его настроек(они определяются плагинами индивидуально), и собственно выполняемых им целей на каждой из фаз жизненного цикла(подробное описание идей, стоящих за этими терминами см. ниже).
Этот элемент несколько чужд общей идеи POM — он несёт не декларативное описание модуля, а инструкции по его сборке конкретным инструментом.
Итоги
Репозитории артефактов
Репозитории артефактов являются выделенными хранилищами результатов сборки, устроенными так, чтобы упростить поиск нужного артефакта (по имени, версии, типу артефакта). Они позволяют группе разработчиков пользоваться результатами работы друг друга без необходимости иметь копии исходных кодов их модулей и выполнять сборку дерева зависимостей с 0. Maven-совместимые репозитарии стали стандартом де факто публикации результатов различных открытых проектов.
Нужно заметить, что pom-файлы, содержащие модель проекта, также являются артефактами и могут хранится в репозитариях вместе со всеми (на самом деле по крайней мере урезанные их версии, содержащие только идентификацию модуля и зависимости, хранятся всегда). Таким образом репозитарий является в том числе источником информации (как миннимум достаточной для дистрибуции) о хранимых в нём модулях.
Утилита управления жизненным циклом
Название получилось достаточно пафосное, однако оно вполне соответствует высокой миссии и сложности предмета.
Прежде чем погрузиться в её функции, необходимо немного познакомится с теорией организации жизненного цикла модуля в Maven. Жизненным циклом называется вся совокупность операций над модулем от инициализации сборки до развёртывания. В процессе прохождения жизненного цикла выполняются определённые операции над модулем, формируются некоторые артефакты. Жизненный цикл разделён на фазы. Каждая фаза подразумевает перевод модуля в новое состояние в результате её прохождения и появление новых артефактов. Каждая предыдущая фаза подготовливает основу для последующей. Список фаз является по сути частью POM, но глобальной, общей для всех модулей. Поный список приводить бессмысленно, но для примера приведу несколько фаз (достаточно интуитивно названных, на мой взгляд 🙂 ) в порядке их следования: compile,… test,… deploy.
В рамках каждой фазы выполняется некоторый набор целей в зависимости от модели конкретного модуля. Цель является конкретной операцией над исходными кодами и/или артефактами.
Также можно попросить выполнить отдельную задачу конкретного плагина. Например есть плагин для генерации Eclipse-проектов, задача «сгенерировать проект» которого по умолчанию не привязывается ни к одной фазе, а вызывается заинтересованными лицами вручную.
Ещё одной крайне интересной функцией mvn является создание заготовки проекта на основе архетипа. Архетип — обобщённый шаблон проекта, традиционно концентрирующийся на его структуре и используемых плагинах. Например есть стандартные архетипы java-библиотеки, web-модуля, и нестандартные, например grails приложение. Важно понимать отличие архетипа от типа проекта. Архетип — только шаблон начальной структуры и отдельных частей проекта, после создания проекта никакой информации о его архетипе не остаётся. Тип проекта — наоборот, часть модели, которая используется на протяжении всего жизненного цикла.
Что получается в сумме
Итак, мы выделили три столпа Maven. Что-же они дают нам вместе?
Заключение
Что-то я местами отклонился от центрального вопроса и вплотную занялся вопросом «как», ну да ладно…
Из всей информации, приведённой выше, можно сделать простой, но почему-то весьма редкий вывод. Maven — не утилита для сборки Java-приложений. Maven — фреймворк для автоматизации большого спектра задач при поддержке проекта. Он никак не связан с языком и платформой, более того он совершенно не обязан что-либо собирать. Вы с помощью описания моделей или написания плагинов превращаете его в тот или иной инструмент. Да, принятая в нём по модель по умолчанию — сборка Java-модулей, но это лишь умолчания…
Надеюсь, что после прочтения топика каждый может уверенно ответить на вопросы, приведённые в начале 😉
Как с помощью maven подключить библиотеку к проекту
Спросите кого-нибудь, для чего вообще нужен Maven — 90 процентов поголовья программистов ответит, что именно для этого и будут во многом правы.
Если в случае с, например, C++ подключение библиотеки к своему проекту — это серьёзный шаг, который гарантированно усложнит сборку до такой степени, что придётся включить инструкции по подключению данной конкретной библиотеки в readme, то в случае с Java это делается легко и непринуждённо — не в последнюю очедь благодаря Maven.
Хочу отметить, что статья предназначена для тех, кто начал изучать java относительно недавно и хотя уже значет из предыдущей статьи, что такое maven — о том, что такое библиотеки, знает не очень хорошо, а как их подключать не знает вообще.
Как добавить в проект новый класс
Для того, чтобы использовать в своём коде какой-нибудь класс, помимо стандартного, нужно этот класс создать, то есть сделать соответствующий файл и написать внутри этого файла соответствующий код.
Свеженаписанный класс должен лежать там же, где и все остальные классы иначе компилятор его не увидит. Теперь, для того, чтобы его использовать, достаточно добавить в использующий его класс соответствующую директиву import.
Предлагаю присутствущим потратить минуту-другую на выражение благодарности капитану Очевидность, а после продолжить чтение.
Как добавить в проект класс, написанный кем-то другим
Ответ, вообще говоря, очевиден — надо скопировать этот класс в свой код.
Кроме того, что немножко менее очевидно, нужно скопировать в свой проект все классы, которые используются классом, ради которого всё затевалось.
Классы, используемые каким-то другим классом, кстати, принято называть зависимостями (dependencies), этого класса.
У такого подхода есть очевидный минус. Для каждого класса надо выискивать зависимости, а потом руками копировать их к себе. Если позже во всей этой куче кода найдётся какой-нибудь баг, то после появления фикса придётся повторить процесс заново.
Как добавить в проект класс, написанный кем-то другим, не копируя его в свой код
Во всех более-менее современных языках программирования эта проблема уже решена.
Всегда можно сказать компилятору, что классы нужно брать не только из директории с проектом, но и из других, указанных программистом директорий. В Java это делается с помощью параметра classpath.
Если вы работаете с Java то понимать, что такое classpath — строго обязательно, но конкретно для того, чтобы добавить к проекту библиотеку с помощью maven, этого знать не нужно. В контексте нашей темы можно считать classpath сущностью, в которой перечислены все места, где компилятор будет искать классы, необходимые приложению. Если какого-нибудь из этих классов нет ни в одном из этих мест, то программа работать не будет.
Теперь для того, чтобы использовать чужой класс, достаточно скачать код с этим классом, и добавить в classpath директорию, в которую скачан этот код.
По сравнению с предыдущим способом это заметный прогресс. Теперь нет никакой необходимости вручную отслеживать все зависимости того единственного класса, который нужен для работы вашего приложения. Для добавки багфиксов и всего такого достаточно просто скачать новую версию кода.
Вот собственно мы и подошли к ответу на вопрос, что такое библиотека.
Что такое библиотека
Библиотекой принято называть тот самый код, корневую директорию которого нужно добавить в classpath. То есть совокупность нужного нам класса и его зависимостей, а также классов, которые не являются зависимостями нужного нам класса, но содержатся в коде.
В случае с Java, код, который мы добавляем в classpath, можно скомпилировать и добавить в classpath уже директорию со скомпилированным кодом.
Ещё можно заархивировать скомпилированный код в формате zip, поменять расширение файла с архивом на jar и добавить в classpath файл уже этот файл. В контексте разработки на Java, jar файл тоже называется библиотекой.
jar файлы не решают ни одной из изложенных выше проблем, но их использование существенно облегчает передачу библиотек между программистами.
Но, есть одна существенная проблема, которую jar файлы тоже никак решить не помогают.
Классы, которые использует библиотека, могут содержаться не в ней, а в какой-нибудь другой библиотеке, которая по аналогии с предыдущим случаем, тоже называется зависимостью.
Как добавить в проект библиотеку, использующую другую библиотеку
Для того, чтобы добавить в проект библиотеку со всеми её зависимостями, придётся эти зависимости скачать и по одной добавить в проект. При обновлении каждой библиотеки зависимости придётся качать заново.
Может случиться так, что при обновлении какой-нибудь зависимости библиотека, класс из которой мы собираемся использовать в своём проекте, перестанет работать корректно — нам придётся внимательно следить за тем, чтобы такого не случилось и ответственно подходить к каждому обновлению, а лучше, обновлять библиотеки только если без обновления нельзя обойтись вообще.
Как убедиться, что обновление зависимости ничего не сломает
Сторого говоря — никак.
Необходимо, конечно, обновить зависимость и запустить юнит тесты. Если они не проходят, то определённо можно сказать, что что-то сломалось.
Если нет, то это является слабым свидетельством, что поломка отсутствует, но ничего не доказывает.
Но положим, что юнит тестам можно доверять. В этом случае при добавлении библиотеки придётся вручную проверить её совместимость с зависимостями запустив прилагаемые юнит тесты и делать это при каждом обновлении. Это, поверьте, мне тяжело.
Для того, чтобы избежать этой нудной и сложной работы, между программистами всего мира существует негласная договорённость. Библиотеки принято версионировать.
При создании библиотеки программист пишет её код, убеждается, что он работает корректно, а потом присваивает этому коду идентификатор, например номер, и после этого делает код доступным для других программистов чтобы они могли использовать эту библиотеку в своём коде.
Если другие программисты находят в библиотеке ошибку, то создатель библиотеки не просто молча её исправляет, а после исправления изменяет идентификатор библиотеки и теперь миру доступно две библиотеки с одинаковым названием, но разными идентификаторами.
Этот идентификатор принято называть версией библиотеки.
Версию библиотеки программист обновляет не только при исправлении ошибок, но и вообще при любом изменении.
Программисты, использующие эту стороннюю библиотеку при создании своих библиотек, или просто программ, указывают в документации не только название, но и версию, с которой их библиотека гарантировано работает корректно.
То есть работу по проверке того, какие версии зависимостей нужно использовать, берёт на себя один человек, остальные просто пользуются плодами его трудов.
Это существенно упрощает ситуацию, но не устраняет необходимости просматривать все зависимости своего кода и зависимости зависимостей для того, чтобы получить полный список библиотек, которые надо подключить к проекту.
При обновлении какой-нибудь из библиотек процесс надо повторить. Это, поверьте мне, мучительно.
Как получить список всех библиотек, нужных проекту и добавить их в проект автоматически
И тут на помощь приходит Maven. Он формализует негласную договорённость между программистами и делает её гласной.
Если для каждой библиотеки есть список зависимостей, с чётко определёнными версиями, то составить список всех нужных проекту библиотек сложности не составляет.
Скопировать эти библиотеки на машину программиста и добавить их в classpath — тоже не высшая математика. Нужно только знать, откуда качать библиотеки и описания их зависимостей, а также в каком формате эти зависимости описаны.
Эти вопросы в Maven успешно решены.
Как подключить библиотеку к Maven проекту
Тут всё в общем-то банально. Библиотека в понимании Maven, является артефактом, нужным для сборки программы.
У каждого артефакта, как мы помним, есть groupId, artifactId и version. Нужно только указать maven, что данный артефакт является зависимостью проекта.
Список зависимостей должен быть обернут тегом dependencies. Каждая отдельная зависимость должна быть обёрнута тегом dependency. Внутри тега dependency в тегах groupId, artifactId и version нужно указать значения соответствующих параметров.
Тут наверное надо дать пример pom.xml с добавленной библиотекой. Вот пример:
Тут мы подключили к проекту библиотеку, с кучей статических методов, выполняющих стандартные задачи. Одной из таких задач является расширение массива и добавление в него дополнительного элемента.
Чтобы скомпилировать код надо написать
Этот код выведет Hello world, но, в отличии от предыдущей статьи, уже новым прогрессивным методом. С помощью библиотеки.
Вот собственно и всё.
Зависимости подключённого к проекту артефакта maven найдёт сам, сам составит список всех библиотек, необходимых проекту, включая зависимости зависимостей и зависимости зависимостей зависимостей, сам скачает их на машину, на которой происходит сборка и сам добавит их в classpath.
Краткое знакомство с Maven
Авторизуйтесь
Краткое знакомство с Maven
Maven — инструмент для автоматизации сборки проектов. С ним работают в основном Java-разработчики, хотя есть плагины для интеграции с C/C++, Ruby, Scala, PHP и другими языками. В статье будут рассмотрены особенности и область применения Maven, описан процесс установки и начала работы, а также разобрана структура файла описания проекта.
Назначение и особенности
Собрать на Java проект уровня «Hello, world!» можно и с помощью командной строки. Но чем сложнее разрабатываемое ПО и чем больше оно использует сторонних библиотек и ресурсов, тем сложнее будет команда для сборки. Maven разработан для облегчения этой работы.
Одна из главных особенностей фреймворка — декларативное описание проекта. Это значит, что разработчику не нужно уделять внимание каждому аспекту сборки — все необходимые параметры настроены по умолчанию. Изменения нужно вносить лишь в том объёме, в котором программист хочет отклониться от стандартных настроек.
Ещё одно достоинство проекта — гибкое управление зависимостями. Maven умеет подгружать в свой локальный репозиторий сторонние библиотеки, выбирать необходимую версию пакета, обрабатывать транзитивные зависимости.
3–5 декабря, Онлайн, Беcплатно
Разработчики также подчёркивают независимость фреймворка от ОС. При работе из командной строки параметры зависят от платформы, но Maven позволяет не обращать внимания на этот аспект.
При необходимости систему сборки можно настроить под собственные нужды, используя готовые плагины и архетипы. А если ничего подходящего не нашлось — можно написать свои.
В этой статье мы будем работать с Maven с помощью командной строки, однако этот фреймворк также интегрирован в Eclipse, IntelliJ IDEA, NetBeans и другие IDE.
Установка, настройка и создание стандартного проекта
Скачать Maven можно с официальной страницы проекта. Там же вас познакомят с минимальными требованиями — на машине должен быть установлен JDK, а также потребуется свободное место на диске, около 500 мегабайт. Это место нужно не для самой установки, оно будет использовано для создания локального репозитория.
На странице скачивания вы найдёте несколько разных архивов, для первого раза лучше использовать готовые бинарники. Исходники потребуются, если захочется всё сломать покопаться в Maven.
В ОС на основе Unix переменную среды можно добавить консольной командной:
Создаём папку для нового проекта и переходим в неё. Далее создаём новый проект. Для этого в консоли выполните команду:
Выглядит довольно сложно, поэтому разберём её по порядку.
Выполнив команду, Maven сгенерирует следующую структуру проекта:
Исходники нашего проекта будут лежать в папке src/main/java (и сейчас там уже есть автоматически сгенерированный файл), но нам сейчас интереснее файл pom.xml в корневом каталоге. Это и есть тот самый файл описания проекта, на основе которого осуществляются все операции Maven. Он написан на языке POM, входящим в семейство XML:
Разберёмся, что всё это значит.
Что значат теги в pom.xml
Кстати, это хороший повод поговорить о жизненном цикле проекта. Maven выполняет сборку последовательными фазами. Приводим их названия на английском, так как они используются в качестве команд.
Поздравляем! Вы собрали проект с помощью Maven. Для более детального изучения инструмента советуем обратить внимание на эти книги и материалы.




