JavaRush /Java блог /Random UA /Все, що ви хотіли знати про Maven - "Java-проект від А до...
Roman Beekeeper
35 рівень

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

Стаття з групи Random UA
Всім привіт, дорогі друзі. Хочу відразу вибачитися: пам'ятаю, я обіцяв, що писатиму за статтею раз на тиждень. Не вийшло. Просто руки не дійшли до того, щоб сісти і нормально написати, а робити так-сяк не хочу. Нити про причини не буду, тому що мені воно не потрібно, і вам точно не цікаво. Проект не мертвий, він був у стазісі:) Ми продовжуємо! І сьогоднішній матеріал присвячений Мавену. "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.codegymcommunity</groupId>
   <artifactId>maven-demo</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>Maven Demo Project</name>

   <url>https://github.com/codegymcommunity/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 на практиці.

Список всіх матеріалів серії на початку цієї статті.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ