JavaRush /Java блог /Java-проекты /Все, что вы хотели знать о Maven - "Java-проект от А до Я...
Roman Beekeeper
35 уровень

Все, что вы хотели знать о Maven - "Java-проект от А до Я"

Статья из группы Java-проекты
Всем привет, дорогие друзья. Хочу сразу извиниться: помнится, я обещал, что буду писать по статье раз в неделю. Не получилось. Просто руки не дошли до того, чтобы сесть и нормально написать, а делать так-сяк не хочу. Ныть о причинах не буду, так как мне оно не нужно, и вам уж точно не интересно. Проект не мертв, он был в стазисе :) Мы продолжаем! И сегодняшний материал посвящен Мавену. "Java-проект от А до Я": Все, что вы хотели знать о Maven - 1

Поговорим о Мавене

Сперва его нужно установить. Разумеется так как у меня мак, показать установку я смогу только для мака. Только вот незадача. Я его давно уже установил, поэтому вам придется сделать это самостоятельно :)
Инструкция по установке Maven есть в этом материале.

Зачем нам Мавен

Мавен — это инструмент для сборки проекта, наряду с Gradle и Ant. Просто в силу того, что я буду использовать его в JRTB (JavaRush Telegram Bot), хочу ввести вас в курс дела. Без системы сборки сейчас не создают ни одного проекта, потому что это упрощает нашу жизнь многократно. Это позволяет:
  • • подтянуть все необходимые библиотеки (в терминах инструментов для сборки — зависимостей (то есть dependency));
  • • определить то, как именно нужно собирать проект и во что (например, хотим мы собирать в WAR или JAR или executable JAR);
  • • задать версию проекта в одном месте так, чтобы при сборке была указана она;
  • • описать проект и его жизненный цикл;
  • • добавлять так называется плагины (калька с английского слова Plugin);
  • • публиковать библиотеки в общем хранилище, чтобы другие проекты смогли подтянуть их как зависимости.
В общем, дел делает много, и все они полезные. Скажу так: для начинающих инженеров не обязательно знать весь функционал от корочки до корочки. Здесь, как и с гитом, важно понимать основу и общие понятия. Этим мы и займемся. Для нас Мавен начинается с XML файла в корне нашего проекта с именем pom.xml. Будем делать все на практике, поэтому для начала создадим наш первый проект в сообществе JavaRush Community. Чтобы сделать все по уму, я воспользуюсь шаблоном для репозитория, где уже настроены базовые вещи, которые я описывал как-то на JR. Чтобы создать, заходим в репозиторий с шаблоном и нажимаем кнопку Use this template:"Java-проект от А до Я": Все, что вы хотели знать о Maven - 2В результате у нас есть первый репозиторий в нашем сообществе :) Стягиваем проект себе локально. Для этого через идею заходим в File -> New -> Project from Version Control. В появившемся окне вводим ссылку на проект на гитхабе (результат будет лучше, если каждый создаст отдельно у себя такой же проект и пройдет все шаги со мной):"Java-проект от А до Я": Все, что вы хотели знать о Maven - 3Нажимаем Clone, и дело в шляпе проект клонирован.

pom.xml всему голова

Все, что нужно, находится в pom.xml. Вся информация о проекте, ее разработчике и том, на каком удаленном репозитории хранится проект. Нас на старте интересуют следующие блоки: <project/> — это главный блок, в котором содержится вся информация о проекте. Все остальные будут явно или транзитивно находиться в нём. Внутри открывающегося тега написано что-то такое:

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://maven.apache.org/POM/4.0.0"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                     http://maven.apache.org/xsd/maven-4.0.0.xsd">
И ко всему прочему следующая строка тоже пишется во всех помниках (сленг такой, мол, от pom.xml :)).

<modelVersion>4.0.0</modelVersion>
А вот дальше уже интереснее: будем описывать, как мы идентифицируем проект, который описывает наш помник. На примере моей библиотеки я опишу, а потом будем добавлять это в наш помник, в новосозданный проект:

<groupId>com.github.romankh3</groupId>
<artifactId>image-comparison</artifactId>
<version>4.4.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Image Comparison</name>
Главное здесь:
  • groupId — это идентификатор девелоперской организации или отдельного инженера. Обычно это домен в обратном порядке. Для примера здесь описан аккаунт romankh3 на гитхабе. Это очень важно. Скажем, у Spring экосистемы это com.springframework. Так можно отличить оригинальный проект от чьего-то ответвления или просто по совпадению имени проекта.
  • artifaceId — это уже имя конкретного проекта, который описывается в этом помнике.
  • version — версия этого проекта. Здесь все ясно, как божий день: добавил новый функционал, починил старый, отрефакторил или сделал какие-то еще изменения — версию увеличил.
  • packaging — здесь мы описываем, как Мавен должен собирать наш проект. То ли в Jar, то ли в War, то ли еще какие-то другие.
  • name — здесь уже более приятное для глаз название проекта.
Есть еще некоторые вещи, которые вовсе не обязательны к заполнению — Мавен заработает и без них, — но если нужно опубликовать библиотеку для общего пользования, добавить их точно стоит. Какие это вещи?
  • • путь к репозиторию проекта, откуда его можно скачать

    
    <url>https://romankh3.github.io/image-comparison/</url>
    

  • • лицензия, под которой этот проект распространяется. Причем она может быть не одна, и поэтому задать нужно таким образом:

    
    <licenses>
     <license>
       <name>The Apache Software License, Version 2.0</name>
       <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
     </license>
    </licenses>
    

  • • информация о разработчиках, которые проект создавали/создают:

    
    <developers>
     <developer>
       <id>romankh3</id>
       <name>Roman Beskrovnyi</name>
       <email>roman.beskrovnyy@gmail.com</email>
     </developer>
    </developers>
    

  • • блок scm, который описывает, как можно получить доступ к проекту:

    
    <scm>
    <connection>git@github.com:romankh3/image-comparison.git</connection>
    <developerConnection>git@github.com:romankh3/image-comparison.git</developerConnection>
     <url>https://github.com/romankh3/image-comparison</url>
    </scm>
    

После того, как мы описали общую информацию, можно добавлять блок с зависимостями (dependencies):

<dependencies>
   <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
       <version>2.26.0</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
       <version>5.5.2</version>
       <scope>test</scope>
   </dependency>
<dependency>
   	<groupId>com.github.romankh3</groupId>
   	<artifactId>image-comparison</artifactId>
   	<version>4.3.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Здесь я добавил две библиотеки для тестирования: они всегда нужны. Как вы могли уже заметить, у зависимостей есть Scope — область применения. В нашем случае указан test, что значит, что в главном коде мы просто не увидим эту зависимость. Далее, чтобы все было по красоте, можно воспользоваться отдельным тегом для выведения версий <properties/>:

<properties>
   <mockito.version>2.26.0</mockito.version>
   <junit.version>5.5.2</junit.version>
   <image.comparison.version>4.3.0</image.comparison.version>
</properties>
Так что блок депенденси можно обновить, используя конструкцию ${PROPERTY_NAME}:

<dependencies>
   <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
       <version>${mockito.version}</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
       <version>${junit.version}</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>com.github.romankh3</groupId>
       <artifactId>image-comparison</artifactId>
       <version>${image.comparison.version}</version>
       <scope>test</scope>
   </dependency>
</dependencies>
Далее идет большой блок <build/>, в котором находится важный блок <plugins/>, при помощи которого можно настраивать процесс сборки. Внутри блока <plugins/> можно добавить один и больше плагинов, как например здесь:

<build>
   <plugins>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
           <version>3.2.0</version>
           <executions>
               <execution>
                   <id>attach-sources</id>
                   <goals>
                       <goal>jar</goal>
                   </goals>
               </execution>
           </executions>
       </plugin>
   </plugins>
</build>
Здесь видно, что я добавил два плагина — maven-source-plugin и maven-javadoc-plugin. В каждом из плагинов есть настройки, атрибуты (параметры), которые можно задавать, тем самым настраивая плагины. Для нас в будущем это будет интересно. Пока что запомним и пойдем дальше. Таким же образом, как и для зависимостей вынесем версии плагинов в <properties/>. Исходя из этого, можно создать следующий помник:

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://maven.apache.org/POM/4.0.0"
        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.github.javarushcommunity</groupId>
   <artifactId>maven-demo</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>Maven Demo Project</name>

   <url>https://github.com/javarushcommunity/maven-demo/</url>

   <properties>
       <mockito.version>2.26.0</mockito.version>
       <junit.version>5.5.2</junit.version>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <source.plugin.version>3.2.0</source.plugin.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.mockito</groupId>
           <artifactId>mockito-core</artifactId>
           <version>${mockito.version}</version>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>org.junit.jupiter</groupId>
           <artifactId>junit-jupiter-api</artifactId>
           <version>${junit.version}</version>
           <scope>test</scope>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-source-plugin</artifactId>
               <version>${source.plugin.version}</version>
               <executions>
                   <execution>
                       <id>attach-sources</id>
                       <goals>
                           <goal>jar</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-javadoc-plugin</artifactId>
               <version>${javadoc.plugin.version}</version>
               <executions>
                   <execution>
                       <id>attach-javadocs</id>
                       <goals>
                           <goal>jar</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>
</project>

Maven lifecycle

У Мавена есть такая вещь, как maven lifecycle. Стоит сказать, что это набор задач (task), которые может выполнить мавен. Задачи могут быть и другие, помимо maven lifecycle. О чем идет речь? Есть набор команд, при помощи которых можно собирать проект (билдить… опять, конечно, калька с английского, но без этого никуда), удалять билды, которые собрал Мавен, устанавливать в Maven local так, чтобы можно было локально подтягивать себе проект как зависимость, и так далее. Сейчас поговорим обо всем подробнее. Перед тем, как написать свое мнение по поводу этих команд, решил почитать, что пишут в интернетах об этом деле… и понял, что описано очень сложно. Нам для работы, для начальной работы, нужно несколько команд. Опишем их:
  • compile — компилировать проект. Это первый этап: в ходе него можно посмотреть, нет ли ошибок компиляции в проекте. Иногда бывает разная чехарда с работой в IDEA, из-за чего появляются проблемы с компиляцией там, где их не должно быть. Так что эта команда расставит все точки над i.
  • test — запускает все тесты, которые работают над JUnit и находятся там, где их ожидает Мавен (src/test/java ваш капитан).
  • package — это следующая команда, которая включает две предыдущие: то есть, внутри нее вначале запускается команда compile, потом на скомпилированный проект натравливается команда test, ну и если все ок и здесь, запускается создание архива (того архива, который мы выбираем в <packaging/>))
  • install — когда мы устанавливаем Мавен на машину, у нас появляется локальный гит-репозиторий, в котором хранятся библиотеки, которые мы скачиваем для проектов. Но прелесть Мавена заключается еще и в том, что мы при помощи команды install можем добавить наш проект в локальный гит-репозиторий и локально использовать наш проект как зависимость. Не верите? Попробуйте :) Таким образом можно достаточно быстро посмотреть, как будет выглядеть ваш проект как зависимость у другого.
  • deploy — это венец всего, что было до этого. Команда, которая дарит возможность добавлять проект не только в локальный репозиторий как install, но и на удаленный, откуда каждый человек с доступом сможет использовать его как зависимость.
  • verify — команда, которая все проверит и скажет, готов ли проект к деплою.
  • clean — разумеется, скомпилированные файлы и архив где-то должны храниться. Для этого у Мавена есть папка target. Это данные, которые проекту не нужны. И перед тем, как собирать проект заново, хорошо бы удалить все, что было до этого. Вот для этого и служит команда clean.

Maven Plugins

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

Список всех материалов серии в начале этой статьи.

Комментарии (17)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #2856674 Уровень 18
24 февраля 2024
По поводу отсутствующего pom.xml Надо добавить Maven в ваш проект в Intelej IDEA Сделать это можно щелкнув прав. кнопкой мыши на корне проекта - add framework support и выбрать maven Если вдруг у вас нет Maven, то скорее всего его следует установить - загуглите как. Этот момент я на самом деле не помню точно - всегда ли есть флаг Maven или нет
Freeflyfish Уровень 22
23 ноября 2023
Да, первые статьи так хорошо зашли, но дальше видимо не было времени, так как непонятно для кого написано про Мавен, ничего не соответствует действиям и картинкам, более того написано делайте свое так будет лучше, но как , для этого же надо как-то показать, и тут бах помник который есть только в проекте romankh3, и никаких пояснений как создать свой, такой же он будет или нет, от чего завист его наполнение, можно ли просто скопипастить, ниже пишут, что в следующей статье все будет, а там еще хуже, пишут создать папки в проекте с main и test и подключить Maven, а на скрине папок нет, тесты тоже уже готовы, В общем жаль, когда столько времени теряешь на то, чтобы разобраться в чужой статье и что же на самом деле должно быть у тебя, то в голове не откладывается четкого понятия что да как, хотя по сути в названии от А до Я, не для новичков совсем, для тех кто уже имел дело и не раз. Если разберусь, то боюсь представить что дальше, ведь это только начало... Автор конечно молодец, для себя памятка хорошая, наверное, но для учащегося только пугает, что опять ничего не понятно и напрасно тратишь время, так как все больше и больше закапываешься в неясностях. Это не хэйт если что, может автор подправит свои статьи позднее или будет писать подробнее с пояснениями, лучше больше - зато понятнее... В любом случае Спасибо за труды!
Кирилл Уровень 35
21 марта 2023
Не совсем пойму, ссылка, с которой копируется, больше не действует?
Кирилл Уровень 35
17 марта 2023
Это жесть жестющая)))
Denis Уровень 33
3 ноября 2022
Я клонировал проект по указанной ссылке. Там не было файла pom.xml. Далее в статье идет описание структуры блоков xml-фала и тут было бы удобно читать статью и паралельно изучать структуру файла "pom.xml", но где взять файл "pom.xml"? Создать блокнотом?
Alex T Уровень 35
5 мая 2021
в той части, где объясняется про плагины - первый скриншот с одним плагином, но текст под ним уверяет, что на нем 2 плагина. в следующем скриншоте плагинов уже действительно 2.
Павел Уровень 35
13 апреля 2021
Чел выложил свой перевод книги Введение в Maven там же есть ссылка на оригинал. А вот цикл старых статей, которые принесут очень большую пользу, если читать внимательно и задаваться вопросом о схемах .xml файлов и основных парадигмах программирования, как императивная (процедурное, ооп) и декларативная (SQL, maven). Читая статью о парадигмах (что по ссылке) явно видишь, что JR делали не профессионалы в обучении((.
Wally Dator Уровень 26
17 марта 2021
я вернулся!
Leftover Уровень 39
16 марта 2021
Непонятно в какой момент и откуда появляется pom.xml :) Например можно сделать правый клик на корне проекта, выбрать Add Framework Support. Выбрать Maven, в появивщемся pom.xml заполнить groupId.
Roman Beekeeper Уровень 35
11 марта 2021
⚡️UPDATE⚡️ Друзья, создал телеграм-канал 🤓, в котором освещаю свою писательскую деятельность и свою open-source разработку в целом. Присоединяйтесь ✌️