Первое знакомство с Maven

Сегодня мы поговорим о таком неотъемлемом инструменте для любого Java-разработчика, как Apache Maven.

Apache Maven - это инструмент управления программными проектами, фреймворк, предназначенный для автоматизации процесса сборки различных проектов на основе описания их структуры в специальных файлах с расширением .pom. POM расшифровывается как Project Object Model (объектная модель проекта), и файлы с расширением .pom фактически написаны на XML. Проект Maven разрабатывается и поддерживается сообществом Apache Software Foundation.

Официальный сайт Apache Maven - https://maven.apache.org/, на нём можно непосредственно скачать Maven для последующей установки и найти всю необходимую документацию для начала работы с Maven.

Слово Maven в переводе c идиша означает примерно следующее: "агрегатор знаний". Свою историю фреймворк начинает во времена, когда производилась попытка упростить процесс сборки на проекте с названием Jakarta Turbine. Было несколько проектов, каждый со своими собственными файлами сборки Ant, и все они существенно отличались между собой. JAR библиотеки фиксировались в системе CVS. Авторы Maven хотели найти стандартный способ собирать проекты, выявить чёткое определение того, что собственно из себя представляет проект, из чего он состоит, а также найти лёгкий способ публикации проектной информации и механизм обмена JAR-библиотеками между несколькими различными проектами.

Результатом этих трудов и изысканий и явился инструмент, который может сейчас быть использован для сборки любого проекта, основанного на Java, и управления им. Авторы Maven искренне надеются на то, что они создали нечто, что сделает каждодневную работу Java-разработчиков проще и в целом поможет с восприятием и пониманием любого Java-проекта.

Цели, которые преследует Maven

Основная цель Maven, согласно официальному сайту авторов, - это позволить разработчику понять полное представление об усилиях, требуемых для разработки проекта и сделать это в самый кратчайший срок. Для достижения данной цели Maven работает в разных направлениях с несколькими проблемными областями:

  • Обеспечение лёгкости процесса сборки
  • Предоставление единой системы сборки
  • Предоставление качественной проектной информации
  • Поощрение лучших практик в разработке

Вкратце остановимся на каждой из этих проблемных областей.

Обеспечение лёгкости процесса сборки

Хотя использование Maven не избавляет от необходимости знать основные механизмы его работы, Maven ограждает разработчиков от множества деталей и погружения в них.

Предоставление единой системы сборки

Maven собирает проект, используя его объектную модель проекта (POM) и набор плагинов. Как только Вы познакомитесь с одним Maven проектом, Вы поймёте и узнаете, как собираются все другие проекты Maven. Это сохраняет время при ориентировании по множеству проектов.

Предоставление качественной проектной информации

Maven предоставляет полезную проектную информацию, которая частично взята из подготовленного Вами файла POM и частично сгенерирована из Ваших же проектных ресурсов. К примеру, Maven может предоставить::

  • Лог изменений, созданный прямо из системы контроля версий
  • Источники с перекрёстными ссылками
  • Списки рассылки, управляемые проектом
  • Зависимости, используемые проектом
  • Отчёты о прогонах Unit-тестов, включающие в себя информацию о тестовом покрытии

Различные 3d-party продукты по анализу кода также поставляют плагины Maven, которые добавляют свои отчёты к стандартной информации, предоставляемой Maven.

Поощрение лучших практик в разработке

Maven нацелен на сбор текущих принципов, относящихся к лучшим практикам разработки, и на обеспечение простоты ведения проекта в этом направлении.

К примеру, спецификация, исполнение и отчёты Unit-тестов являются частью штатного цикла сборки с использованием Maven. Текущие лучшие практики в области Unit-тестирования были использованы как методические рекомендации:

  • Хранение исходного кода для тестов в отдельном, но параллельном дереве исходных кодов
  • Использование правил именования тест-кейсов для обнаружения и исполнения тестов
  • Предоставление тест-кейсам возможности установить своё окружение вместо того, чтобы кастомизировать сборку для подготовки тестов

Maven также является отличным ассистентом и помогает в части жизненного цикла проекта, например, помогает с выпуском релиза и процессом управления проблемами.

Maven предлагает некоторые рекомендации по организации структуры директорий Вашего проекта. Как только Вы узнаете и запомните типовую структуру директорий, Вы сможете с лёгкостью ориентироваться и в других проектах, использующих Maven.

В то время, как Maven использует взвешенный и подкреплённый мнением компетентных специалистов подход к типовой структуре проекта, некоторые проекты могут быть несовместимы с подобной структурой по историческим причинам. Хотя Maven и спроектирован так, чтобы быть гибким в соответствии с потребностями различных проектов, всё же он не может удовлетворить все подобные ситуации без ущерба для собственных целей.

Если Ваш проект имеет нестандартную структуру сборки, которая не может быть реорганизована, Вам придётся отказаться от некоторых функций Maven (или вообще от его использования).

Чем же Maven не является?

Возможно, Вам приходилось слышать примерно такие вещи о Maven:

  • Maven - это инструмент работы с сайтами и документацией
  • Maven расширяет Ant, чтобы дать Вам возможность загружать зависимости
  • Maven - это набор переиспользуемых Ant-скриптлетов 

В то время как Maven поддерживает и делает все эти вещи, они не являются единственными его функциями и особенностями, и цели инструмента отличны от всего вышеперечисленного.

Установка Maven

Существуют различные варианты использования Maven, и некоторые разработчики предпочитают устанавливать его отдельно. Другие же используют встроенный Maven, которые интегрирован во все известные ныне среды разработки, такие как IntelliJ IDEA, Eclipse или NetBeans.

Если Вы выбираете для себя первый вариант и хотите установить Maven на свой компьютер, то опишу лишь кратко основные шаги, которые потребуется для этого сделать. Установка Maven крайне проста и изящна - нужно просто скачать дистрибутив требуемой версии Maven с официального сайта. Это будет обычный архив, который следует распаковать в нужную Вам директорию и добавить полный путь к вложенной директории bin к Вашей переменной окружения PATH. Можно сказать, что это основные шаги по отдельной установке Maven. Детально с шагами установки по этому варианту можно ознакомиться в инструкции на официальном сайте фреймворка: https://maven.apache.org/install.html

Для того, чтобы попробовать Maven в действии, мы будем использовать несколько другой вариант: воспользуемся как раз тем, что Maven, как я уже сказал, хорошо интегрирован в ключевые среды разработки. В этой статье мы будем использовать среду разработки IntelliJ IDEA от компании JetBrains и рассмотрим с её помощью пример сборки проекта на Maven.

Также у Вас уже должна быть установлена версия JDK, желательно не ниже JDK 8 (для статьи я использую 1.8.0_271), но если Ваша версия старше/младше указанной, это не так критично для демонстрации работы с Maven. Если JDK ещё не установили, его можно скачать с официального сайта Oracle: https://www.oracle.com/java/technologies/downloads/

Также ссылка на скачивание среды разработки IntelliJ IDEA, которую я буду использовать (скачивать нужно Community версию для целей ознакомления, т.к. она бесплатна в отличие от Ultimate): https://www.jetbrains.com/ru-ru/idea/download/

Итак, при запуске IntelliJ IDEA выбираем "New Project":

Далее, мы должны увидеть примерно следующее: в поле "Project SDK" у нас должна быть выбрана установленная на машине версия JDK (в моём случае видно, что это версия 1.8.0_271). Отмечаем галочку "Create from archetype", после чего ожидаем подгрузки списка архетипов, из которых будет создаваться наш новый тестовый проект для знакомства с Maven. Когда список прогрузится, ищем в нём и выбираем следующий: org.apache.maven.archetypes:maven-archetype-quickstart и жмём "Next":

На следующем шаге выбираем местоположение нашего нового Maven-проекта и его имя. В качестве имени я выбрал MyMavenSample, после ввода жмём "Next":

На следующем шаге у Вас отобразится следующая информация о Maven: видим, что будет использоваться версия Maven 3, встроенная (Bundled, версии 3.6.3), также видим важные параметры Maven о которых постараемся поговорить позже в других статьях - "User settings file" и "Local repository". Первый параметр указывает местоположение файла настроек Maven, а второй - на локальный репозиторий Maven. В локальный репозиторий Maven будет загружать различные зависимости (dependencies), т.е. JAR-библиотеки и артефакты, от которых будет зависеть проект (и другие будущие проекты, если они будут собираться на этой же версии Maven и текущими настройками). Оба пути желательно запомнить/записать, т.к. они могут пригодиться нам впоследствии при дальнейшем погружении в механизмы работы с Maven. Менять на экране ничего не нужно, просто ознакомились и жмём "Finish":

После нажатия кнопки "Finish" среда разработки будет отображать индикатор выполнения процесса подготовки нашего свежего Maven-проекта. По окончанию этого процесса, если всё прошло по описанным выше шагам, мы увидим в консоли выполняемые шаги Maven сборки и в конце сообщение об успешной сборке - "BUILD SUCCESS":

Как видим, наш проект успешно собрался, причём мы не написали для этого ни единой строчки кода, Maven уже всё подготовил за нас! Согласитесь, это очень неплохо.

Также по умолчанию в редакторе IDEA откроет сразу наш файл объектной модели проекта, или POM-файл с именем pom.xml. Он также подготовлен автоматически, нам не пришлось создавать его вручную, давайте взглянем, как он устроен:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>MyMavenSample</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>MyMavenSample</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

Можем видеть, что Maven и выбранный нами архетип quickstart автоматически определил необходимые плагины и включил их в сборку нашего проекта, также сразу заготовил и добавил зависимость (dependency) на junit 4.11 - и она уже может использоваться для написания и запуска Unit-тестов с помощью библиотеки тестов JUnit.

Обратите внимание на блок properties - в нём задаются различные свойства нашего проекта, в частности, кодировка исходных файлов project.build.sourceEncoding выставлена в UTF-8.

Также видим свойства maven.compiler.source и maven.compiler.target. Они используются для задания опций компилятора javac с соответствующими названиями -source и -target. Если Вам потребуется компиляция проекта в другую версию, Вы всегда сможете поменять значения этих свойств, и это обеспечит требуемую конфигурацию compiler-плагина для Maven для простановки этих опций во время компиляции исходных файлов Вашего приложения.

Например, если Вы хотите использовать языковые фичи Java 8 (значение -source 1.8) и также хотите, чтобы скомпилированные классы были совместимы с JVM 1.8 (-target 1.8), то Вы можете либо добавить эти два свойства, которые являются именами свойств по умолчанию для параметров плагина, в блоке properties:

<project>
  <!-- ... -->
  <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
  <!-- ... -->
</project>

либо же Вы можете сконфигурировать плагин maven-compiler-plugin напрямую через XML-тег configuration и вложенные в него source и target:

<project>
  <!-- ... -->
  <build>
    <!-- ... -->
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
    <!-- ... -->
  </build>
  <!-- ... -->
</project>

Итак, наше первое приложение с использованием Maven успешно собрано. Давайте взглянем, что ещё для нас подготовил Maven: если открыть в окне "Project" структуру нашего проекта, мы увидим следующее - для нас уже заготовлен класс нашего приложения App, который выводит на экран строку "Hello World!", а также простой демонстрационный JUnit-тест с именем AppTest:

 

Запустим наше приложение с помощью контекстного меню на файле класса App:

Результатом будет ожидаемый вывод на экран строки "Hello World":

Также посмотрим на Unit-тест AppTest, всё, что он делает - это команда assertTrue(true), которая всегда будет успешной - этот тест лишь для демонстрации и не несёт никакой полезной функциональности:

Если также запустить тест через контекстное меню на файле AppTest, то увидим результат - наш тест успешно исполнился:

Итак, мы познакомились с Maven, попробовали собрать с Вами небольшой проект с использованием простого архетипа quickstart для Maven. Надеюсь, материал был полезен и помог сформировать общее представление о том, что такое Maven, его краткую историю и какие цели он преследует, а также как помогает Java-разработчику при формировании структуры проекта и в процессе сборки проекта. Более детальное погружение в Maven, его функциональность и дополнительные возможности, надеюсь, сможем сделать в следующих статьях.

Добавить комментарий