Maven. Структура проекта. POM
Дорогу осилит идущийСегодня мы начнем работу с первой из рассматриваемых систем сборок - Maven. Знакомиться с ней будем на примере простого проекта, оперируя, в основном, функциональностью, предоставляемой IDEA.
Стоит понимать, что Maven сам по себе предоставляет консольный интерфейс и красивый GUI в среде разработки - лишь репрезентация консольных функций. И иногда графического интерфейса не хватает или он может быть неудобен в отдельных случаях. Но в наших задачах мы вряд ли это встретим.
Пример простейшего проекта с подключенным логгером можно посмотреть по ссылке. В статье будут периодические отсылки на него.
Структура проекта
Создадим простой maven-проект. В самом базовом варианте для этого в IDEA достаточно выбрать Maven в качестве системы сборки при создании нового проекта. В результате будет создан проект со следующей структурой:
Разберемся, что есть что.
Project home - корневая директория проекта. В нашем случае это maven-sample.
В этой директории можно найти несколько других папок и файл - pom.xml. С файлом разберемся в следующем разделе, а пока сосредоточимся на папках.
src - папка, в которой лежат исходники проекта - сам исходный код, файлы конфигураций библиотек и прочее, что нужно проекту для запуска и работы приложения или тестов. В целом, ничего принципиально нового здесь нет.
Внутри можно заметить еще две папки с одинаковым содержимым:
- main. Все то, что нужно самому проекту для компиляции и запуска. Если взять за пример проект practical-tasks и перевести на Maven, все его содержимое окажется именно в папке main: пакеты и классы - в папке java, а файлы (для практики о I/O и SQL-скрипты) - в папке resources.
Если же за пример возьмем logger-sample - в resources попал бы файл log4j2.properties. Возможно, это было не очевидно из прошлого примера.
- test. Здесь логика схожа. Папка java будет содержать классы с тестами - юнит-тестами, интеграционными - не важно. А в resources будут лежать конфигурации и файлы, необходимые для тестов.
В целом, с юнит-тестированием мы будем знакомиться чуть позже. Там же разберем наполнение директории test более подробно.
target. При создании проекта эта директория отсутствует (и обычно не добавляется в git-репозиторий). Она появится после выполнения какой-либо задачи. Ее содержимое может отличаться - в зависимости от того, какую задачу выполняли. Если не вдаваться в детали - именно в этой директории можно найти скомпилированные классы и/или jar-файл, сформированный на базе проекта*.
* Пока мы не знакомы с основной терминологией, буду стараться использовать обтекаемые формулировки. Постепенно разберем, как все обстоит на самом деле.
Полагаю, на этом этапе все достаточно просто. Поэтому переходим к сердцу и мозгу maven-проекта - pom.xml (он же помник). Но сначала небольшое отступление.
Формат XML
Прежде чем углубимся в логическое наполнение помника, разберемся с используемым расширением - с ним вы будете сталкиваться регулярно в различных контекстах.
XML (eXtensible Markup Language) является языком разметки на основе тегов. Если вы знакомы с HTML - основные принципы те же. Но в отличии от HTML, набор тегов не фиксирован языком.
Тег - основная структурная единица данного языка вида
<sthTag> some information </sthTag>
Представляющая собой:
- Имя тега, заключенное в угловые скобки - открывающий тег;
- Какую-то информацию (текст или другие теги) - содержимое тега. Так же может быть пустым;
- Слэш + имя тега в угловых скобках.
!NB: Также есть упрощенный формат записи тегов, подходящий, если тег не имеет внутреннего содержимого и является своего рода меткой:
<sthMarker/>
Для наших целей пока не актуально, но не удивляйтесь, если встретите.
Подобный формат записи позволяет построить древовидную структуру файла, где содержимых одних тегов могут выступать другие теги. Это позволяет описывать достаточно сложные сущности с большим уровнем вложенности. Можно провести аналогию с объектами, где один объект содержит другие объекты, которые могут содержать третьи объекты или примитивные типы.
Такой подход достаточно удобен для описания различных конфигураций, что и стало причиной его использования в Maven.
Кроме этого, теги могут содержать атрибуты - поля с данными внутри угловых скобок открывающего тега - как правило, они содержат дополнительную информацию, относящуюся к конкретно этому использованию тега. Атрибутов у одного тега может быть несколько, но их состав определяется конкретным тегом*.
Пример использования тега с атрибутами:
<sthTag attribute1="some data" attribute2="22"> some information </sthTag>
* Строго говоря, это не так. В рамках XML мы можем использовать любые теги и давать им любые атрибуты. И то, и другое ограничено лишь нашей фантазией и синтаксическими ограничениями XML. Но практика использования подразумевает, что наш файл будет использоваться для получения определенных данных, как Maven использует pom.xml для получения конфигурации приложения. Соответственно, набор тегов ограничен конкретным потребителем файла и ожидает строго определенные теги и атрибуты.
Конечно, в файл можно дописать что угодно, но это не имеет смысла. Более того, скорее всего, такой файл парсер признает невалидным, потому что будет опираться на используемые пространства имен, содержащие допустимые теги. Этот момент подсвечен в комментариях внутри pom.xml нашего примера.
Так же отмечу несколько базовых моментов при работе с XML:
- Тег обязательно должен быть закрыт. Незакрытый тег означает невалидный файл.
- Тег, открытый вторым, не может быть закрыт после тега, открытого первым:
Валидная запись:
<tag1>
<tag2>
<tag3>value 1</tag3>
<tag3>value 2</tag3>
<tag4>value 3</tag4>
</tag2>
</tag1>
Невалидная запись:
<tag1>
<tag2>
<tag3>value 1</tag3>
<tag3>value 2</tag3>
<tag4>value 3</tag4>
</tag1>
</tag2>
Пример выше наглядно демонстрирует, что табуляция облегчает отслеживание незакрытых тегов. Невалидный вариант смотрится неестественно.
Заодно предлагаю обратить внимание на еще один факт: теги, содержащие текстовую информацию, допустимо записывать в одну строку. Для тегов, содержащих другие теги, такой подход будет некорректным
Конечно, это далеко не исчерпывающая информация для комфортной работы с XML, но для первого знакомства ее будет достаточно. Теперь можем перейти к содержимому pom.xml
pom.xml
POM - аббревиатура от Project Object Model.
pom.xml, как можно догадаться, является ключевым файлом конфигурации для Maven. Именно в нем описываются параметры проекта, его зависимости, указываются используемые плагины, настройки сборки и многое другое.
На самом деле, pom-файлов в проекте может быть несколько. Как правило, существует корневой pom-файл (мы его видели на схеме выше), а также pom-файлы у каждого модуля. Мы рассмотрим этот аспект немного подробнее в процессе знакомства с модульной структурой. Схема выше демонстрирует одномодульный проект, поэтому и pom-файл в ней лишь один.
Полные перечень тегов для pom.xml можно найти в документации: https://maven.apache.org/pom.html
Там, безусловно, очень много информации, но рекомендую хотя бы пройти по верхнеуровневым заголовкам, чтобы понимать, какого рода информацию может содержать этот файл. В дальнейшем можно будет изучать информацию по конкретным тегам по мере необходимости.
На данном этапе мы не можем полноценно понять, что лежит в файле примера - пока у нас слишком мало знаний об инструментах системы сборки. Но можем рассмотреть хотя бы верхнеуровневые блоки, чтобы понять, какого рода информация в них хранится. Предлагаю изучить комментарии в файле: ссылка
По итогу все достаточно просто (если не обращать внимания на монструозный уровень вложенности отдельных конструкций). Подчеркнем основные моменты:
- Указываем метаинформацию о файле. По сути, это относится к XML, предоставляя информацию для парсера, а не напрямую к pom.xml. Похожую строчку вы увидите почти в любом xml-файле;
- Указываем информацию для процессора помника. По сути - допустимые теги, а также правила валидации и обработки содержимого, но уже именно для Maven;
- Описываем базовую информацию о нашем проекте - название, версия, требуемая версия JDK;
- Указываем интересующие нас зависимости. В нашем случае - логгер;
- Добавляем плагин, позволяющий запустить приложение и даем указания для него - задаем точку входа (класс Main).
Более детально будем разбираться в дальнейших уроках. Нам предстоит плотно познакомиться с терминологией и инструментами Maven, чтобы понять, что именно мы написали в нашем помнике.
Запуск приложения
Чтобы убедиться, что пример рабочий, нужно его запустить. Для этого нам нужно скомпилировать проект и запустить его.
По сути, для мавена это выглядит как команда:
mvn clean compile exec:java
Используя ее мы:
- Очищаем результаты предыдущей сборки, если таковая была;
- Компилируем исходники проекта;
- Запускаем проект.
Само собой, в следующих уроках мы разберемся, что есть что в данной команде.
Поскольку мы ориентированы на работу через GUI IDEA, рассмотрим, как это можно сделать в данном случае.
До этого мы запускали проекты, по сути, командой java, которая скрывалась под знакомым нам зеленым треугольником.
Теперь пришло время самим сказать, что этому зеленому треугольнику нужно делать:
Так как конфигурацию мы задаем для Maven - нет необходимости указывать mvn (это и есть запуск инструмента Maven в консоли).
После этого применяем изменения и наслаждаемся правильной работой зеленого треугольника!
С теорией на сегодня все!

В качестве практики предлагаю попытаться сконфигурировать и запустить мавен-проект, который был разобран в рамках статьи.
Если что-то непонятно или не получается – welcome в комменты к посту или в лс:)
Канал: https://t.me/ViamSupervadetVadens
Мой тг: https://t.me/ironicMotherfucker
Дорогу осилит идущий!