Написать пост

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

Аватар Сергей Штукатуров

Фрейворк Maven предназначен для автоматизации сборки проектов. Эта статья о том, как начать с ним работу и как забобраться в файле описания проекта pom.xml.

Обложка поста Краткое знакомство с Maven

Maven — инструмент для автоматизации сборки проектов. С ним работают в основном Java-разработчики, хотя есть плагины для интеграции с C/C++, Ruby, Scala, PHP и другими языками. В статье будут рассмотрены особенности и область применения Maven, описан процесс установки и начала работы, а также разобрана структура файла описания проекта.

Назначение и особенности

Собрать на Java проект уровня «Hello, world!» можно и с помощью командной строки. Но чем сложнее разрабатываемое ПО и чем больше оно использует сторонних библиотек и ресурсов, тем сложнее будет команда для сборки. Maven разработан для облегчения этой работы.

Одна из главных особенностей фреймворка — декларативное описание проекта. Это значит, что разработчику не нужно уделять внимание каждому аспекту сборки — все необходимые параметры настроены по умолчанию. Изменения нужно вносить лишь в том объёме, в котором программист хочет отклониться от стандартных настроек.

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

Разработчики также подчёркивают независимость фреймворка от ОС. При работе из командной строки параметры зависят от платформы, но Maven позволяет не обращать внимания на этот аспект.

При необходимости систему сборки можно настроить под собственные нужды, используя готовые плагины и архетипы. А если ничего подходящего не нашлось — можно написать свои.

В этой статье мы будем работать с Maven с помощью командной строки, однако этот фреймворк также интегрирован в Eclipse, IntelliJ IDEA, NetBeans и другие IDE.

Установка, настройка и создание стандартного проекта

Скачать Maven можно с официальной страницы проекта. Там же вас познакомят с минимальными требованиями — на машине должен быть установлен JDK, а также потребуется свободное место на диске, около 500 мегабайт. Это место нужно не для самой установки, оно будет использовано для создания локального репозитория.

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

Архив можно распаковать в любое удобное место. После этого нужно добавить путь к папке bin из распакованного архива в переменную среды PATH. В Windows нужно зайти в настройки параметров системы (вызывается комбинацией клавиш Win+Pause или щелчком правой кнопкой мыши по ярлыку «Мой / Этот компьютер» -> «Свойства»), и выбрать пункт «Дополнительные параметры системы». В правом нижнем углу нажмите кнопку «Переменные среды». Выберите переменную PATH, нажмите «Изменить», в открывшемся окне — «Создать» и добавьте путь. Обратите внимание, путь должен вести именно к папке bin.

В ОС на основе Unix переменную среды можно добавить консольной командной:

			export PATH=/opt/apache-maven-3.6.0/bin:$PATH
		

Проверить, всё ли сделано правильно, можно с помощью консольной команды mvn -v. Вы должны увидеть что-то подобное:

			Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-24T21:41:47+03:00)
Maven home: C:\apache-maven-3.6.0\bin\..
Java version: 10.0.1, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-10.0.1
Default locale: ru_RU, platform encoding: Cp1251
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
		

Создаём папку для нового проекта и переходим в неё. Далее создаём новый проект. Для этого в консоли выполните команду:

			mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
		

Выглядит довольно сложно, поэтому разберём её по порядку.

archetype:generate это так называемая цель. Она указывает Maven, что нужно создать проект из архетипа. Дальше с помощью -D мы указываем определённые параметры генерации.

  • groupId=com.mycompany.app указывает на разработчика ПО, там вы можете указать доменное имя своей компании.
  • artifactId=my-app — название проекта. Maven оперирует так называемыми артефактами. Это приложения, плагины, архетипы и другие проекты. И ваша разработка также будет считаться артефактом.
  • archetypeArtifactId=maven-archetype-quickstart указывает, какой архетип использовать в качестве шаблона для создания приложения. Как видите, это тоже артефакт. Указанный архетип создаст простой проект, сгенерирует структуру каталогов и даже заботливо положит в папку исходников программу «Hello, world!», чтобы вам не пришлось самому писать её в двухсотый раз.
  • archetypeVersion=1.4 указывает на версию артефакта «архетип».
  • interactiveMode=false отключает создание проекта в интерактивном режиме. Вы можете запустить цель archetype:generate без параметров, и Maven предложит установить параметры в процессе генерации. В данном случае нам это не нужно. Кстати, отключить интерактивный режим можно параметром -B. Полный список параметров для mvn можно получить по команде mvn -h.

Выполнив команду, Maven сгенерирует следующую структуру проекта:

			my-app

|-- pom.xml

`-- src

    |-- main

    |     `-- java

    |         `-- com

    |             `-- mycompany

    |                 `-- app

    |                     `-- App.java

    `-- test

        `-- java

            `-- com

                `-- mycompany

                    `-- app

                        `-- AppTest.java
		

Исходники нашего проекта будут лежать в папке src/main/java (и сейчас там уже есть автоматически сгенерированный файл), но нам сейчас интереснее файл pom.xml в корневом каталоге. Это и есть тот самый файл описания проекта, на основе которого осуществляются все операции Maven. Он написан на языке POM, входящим в семейство XML:

			<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>com.mycompany.app</groupId>
   <artifactId>my-app</artifactId>
   <version>1.0-SNAPSHOT</version>
   <name>my-app</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>
         <plugins><...></plugins>
      </pluginManagement>
   </build>
</project>
		

Разберёмся, что всё это значит.

Что значат теги в pom.xml

Тег project является базовым и содержит всю информацию о проекте. В заголовке указана информация, необходимая Maven для понимания файла pom.xml. Тег modelVersion указывает на текущую версию POM. Эти два тега обычно генерируются автоматически, менять их не нужно.

Затем идёт информация, формирующая уникальный идентификатор проекта, теги groupId и artifactId. Её мы задавали выше при генерации из архетипа. Тег version тоже входит в эту группу. Он обычно генерируется и обновляется автоматически. После номера версии идёт суффикс -SNAPSHOT. Это означает, что проект находится в стадии разработки. В процессе выпуска ПО фреймворк уберёт этот суффикс, а если разработка продолжится — автоматически увеличит номер версии. Вместе эти три тега позволяют однозначно идентифицировать артефакт.

name содержит отображаемое имя артефакта, а url — ссылку на сайт. Поскольку сайт не задан при генерации, pom.xml содержит напоминание об этом в виде комментария. Кроме того, можно добавить краткое описание в description. Эти три тега зачастую используются при формировании документации.

Дальше мы видим блок properties. Здесь указаны особые настройки, такие как кодировка файла и используемая версия компилятора Java. Без этого блока можно обойтись, положившись на настройки по умолчанию.

Следом идёт очень важный блок dependencies. В нём описываются все используемые в проекте зависимости. Каждую необходимо выделить тегом dependency и указать уникальные идентификационные данные: groupIdartifactId и version. Maven сам подгрузит транзитивные зависимости. Кроме того, с помощью тега scope можно указать этапы, на которых будет использован артефакт. Сейчас в pom.xml всего одна зависимость — артефакт JUnit, библиотека для модульного тестирования на Java, которая будет использоваться только на стадии тестирования.

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

  1. Проверка — validate. Фреймворк проверяет, корректен ли проект и предоставлена ли вся необходимая для сборки информация.
  2. Компиляция — compile. Maven компилирует исходники проекта.
  3. Тест — test. Проверка скомпилированных файлов. В нашем случае будет использована библиотека JUnit.
  4. Сборка проекта — package. По умолчанию осуществляется в формате JAR. Этот параметр можно изменить, добавив в project тег packaging.
  5. Интеграционное тестирование — integration-test. Maven обрабатывает и при необходимости распаковывает пакет в среду, где будут выполняться интеграционные тесты.
  6. Верификация — verify. Артефакт проверяется на соответствие критериям качества.
  7. Инсталляция — install. Артефакт попадает в локальный репозиторий. Теперь его можно использовать в качестве зависимости.
  8. Размещение проекта в удалённом репозитории — deploy, — финальная стадия работы.

Эти фазы упорядочены и выполняются поочерёдно. Если необходимо собрать проект, система последовательно проведёт оценку, компиляцию и тестирование, и только после этого сборку. Помимо этого есть две фазы, выполняющиеся отдельно, только прямой командой. Это очистка — clean, удаляющая предыдущие сборки, и создание документации для сайта — site.

Закончим рассмотрение pom.xml секцией build. Она не является обязательной, в данном pom.xml в неё включены плагины из архетипа, однако можно обойтись и без них. Плагинов для Maven тысячи, освоившись с применением фреймворка вы сможете сами подобрать себе необходимые.

В проектах чуть серьёзнее, чем вычисление факториала, приходится использовать внешние ресурсы. Maven способен автоматически обрабатывать файлы ресурсов и размещать их в сборке проекта. Для этого их нужно разместить в папке src/main/resources. Файлы будут упакованы с сохранением внутренней структуры каталогов. Если же по какой-то причине нужно переопределить каталог, используйте вложенные теги resources, resource, directory в секции build:

			<build>
    <resources>
        <resource>
            <directory>src/main/another_resources_directory</directory>
        </resource>
    </resources>
</build>
		

Итак, с файлом описания мы разобрались. Попробуем собрать проект. Для этого перейдём в корневую папку и выполним команду нужной фазы, mvn package. Получим отчёт о сборке:

			[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\javaProjects\new_project\my-app\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\javaProjects\new_project\my-app\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\javaProjects\new_project\my-app\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\javaProjects\new_project\my-app\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.217 s - in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: C:\javaProjects\new_project\my-app\target\my-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  20.670 s
[INFO] Finished at: 2019-02-17T02:25:07+03:00
[INFO] ------------------------------------------------------------------------
		

Теперь в корневом каталоге проекта вы обнаружите папку target, а в ней готовый файл my-app-1.0-SNAPSHOT.jar.

Запустите команду java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App — вы должны увидеть «Hello World!».

Поздравляем! Вы собрали проект с помощью Maven. Для более детального изучения инструмента советуем обратить внимание на эти книги и материалы.

Следите за новыми постами
Следите за новыми постами по любимым темам
115К открытий115К показов