JavaRush /Курсы /JSP & Servlets /Продвинутая сборка Maven-проекта

Продвинутая сборка Maven-проекта

JSP & Servlets
2 уровень , 0 лекция
Открыта

1.1 Список плагинов для сборки в Maven

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

Плагин Описание
1 maven-compiler-plugin Управляет Java-компиляцией
2 maven-resources-plugin Управляет включением ресурсов в сборку
3 maven-source-plugin Управляет включением исходного кода в сборку
4 maven-dependency-plugin Управляет процессом копирования библиотек зависимостей
5 maven-jar-plugin Плагин для создания итогового jar-файла
6 maven-war-plugin Плагин для создания итогового war-файла
7 maven-surefire-plugin Управляет запуском тестов
8 buildnumber-maven-plugin Генерирует номер сборки

Каждый плагин по-своему интересен, но разобрать нам придется их все. Начнем мы с главного – плагина по управлению компиляцией.

1.2 Плагин компиляции maven-compiler-plugin

Самый популярный плагин, позволяющий управлять версией компилятора и используемый практически во всех проектах, – это компилятор maven-compiler-plugin. У него имеются настройки по умолчанию, однако практически в каждом проекте их нужно задать заново.

В самом простом варианте в плагине нужно задать версию исходного Java-кода и версию Java-машины, под которые осуществляется сборка:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.2</version>
    <configuration>
        <source>1.11</source>
        <target>1.13</target>
        <encoding>UTF-8</encoding>
    </configuration>
</plugin>

В примере выше мы задаем три параметра Java-компилятора: source, target и encoding.

Параметр source позволяет нам задать версию Java для наших исходников. Параметр target – версию Java-машины, под которую нужно скомпилировать классы. Если версия кода или Java-машины не задана, то по умолчанию используется параметр 1.3

Наконец параметр encoding позволяет указать кодировку Java-файлов. Мы указали UTF-8. Сейчас практически все исходники хранятся в кодировке UTF-8. Но если этот параметр не указан, то выберется текущая кодировка операционной системы. Для Windows – это кодировка Windows-1251.

Также бывают случаи, когда компьютер, на котором производится сборка имеет несколько установленных версий Java: для сборки разных модулей и/или разных проектов. В этом случае в переменной JAVA_HOME может быть указан только путь к одной из них.

Кроме того, бывают разные реализации Java-машины: OpenJDK, OracleJDK, Amazon JDK. И чем больше проект, тем сложнее его структура. Но вы можете явно задать плагину путь к компилятору javac с помощью тега . Его добавили специально на этот случай.

Плагин maven-compiler-plugin имеет две цели (goals):

  • compiler:compile – компиляция исходников, по умолчанию связана с фазой compile
  • compiler:testCompile – компиляция тестов, по умолчанию связана с фазой test-compile.

Также можно указать список аргументов, которые будут переданы javac-компилятору в командной строке:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.2</version>
    <configuration>
        <compilerArgs>
            <arg>-verbose</arg> <arg>-Xlint:all,-options,-path<arg>
        </compilerArgs>
    </configuration>
</plugin>

1.3 Плагин создания jar-файла maven-jar-plugin

Если вы захотите собрать с помощью Maven свою собственную jar-библиотеку, то вам понадобится плагин maven-jar-plugin. Этот плагин умеет много полезных вещей.

Пример такого плагина:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <includes> <include>**/properties/*</include> </includes>
        <archive> <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile> </archive>
    </configuration>
</plugin>

Во-первых, с его помощью можно указать, какие файлы попадут в библиотеку, а какие – нет. С помощью тегов <include> в секции <includes> можно задать список директорий, чей контент нужно добавить в библиотеку.

Во-вторых, каждая jar-библиотека должна иметь манифест (файл MANIFEST.MF). Плагин сам положит его в нужное место библиотеки, вам всего лишь нужно указать, по какому пути его взять. Для этого используется тег <manifestFile>.

И наконец, плагин может самостоятельно сгенерировать манифест. Для этого вместо тега <manifestFile> вам нужно добавить тег <manifest> и в нем указать данные для будущего манифеста. Пример:

<configuration>
    <archive>
        <manifest>
            <addClasspath>true</addClasspath>
            <classpathPrefix>lib/</classpathPrefix>
            <mainClass>com.javarush.MainApplication</mainClass>
        </manifest>
    </archive>
</configuration>

Тег <addClasspath> определяет необходимость добавления в манифест CLASSPATH.

Тег <classpathPrefix> позволяет дописывать префикс (в примере lib) перед каждым ресурсом. Определение префикса в <classpathPrefix> позволяет размещать зависимости в отдельной папке.

Да, вы можете размещать библиотеки внутри другой библиотеки. И вас ждет много сюрпризов, когда вам нужно будет куда-то передать путь к properties-файлу, который находится в jar-библиотеке, которая находится в jar-библиотеке.

И наконец, тег <mainClass> указывает на главный исполняемый класс. “Что за главный исполняемый класс?”, – спросите вы. А все дело в том, что Java-машина может запустить программу, которая задана не только Java-классом, но и jar-файлом. И именно для такого случая нужен главный стартовый класс.

1.4 Плагин генерации номера сборки buildnumber-maven-plugin

Очень часто jar-библиотеки и war-файлы включают в себя информацию с названием проекта и его версией, а также версией сборки. Мало того, что это полезно для управления зависимостями, так еще и упрощает тестирование: понятно, в какой версии библиотеки ошибка исправлена, а в какой – добавлена.

Чаще всего эту задачу решают так – создают специальный файл application.properties, который содержит всю нужную информацию и включают его в сборку. Так же можно настроить сценарий сборки так, чтобы данные из этого файла перекочевывали в MANIFEST.MF и тому подобное.

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

# application.properties
app.name=${pom.name} app.version=${pom.version} app.build=${buildNumber}

Значения всех трех параметров будут подставляться на этапе сборки.

Параметры pom.name и pom.version будут браться прямо из pom.xml. А для генерации уникального номера сборки в Maven есть специальный плагин – buildnumber-maven-plugin. Смотрите пример ниже:

<packaging>war</packaging>
<version>1.0</version>
<plugins>
    <plugin>
        <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> <version>1.2</version>
        <executions> <execution> <phase>validate</phase> <goals> <goal>create</goal> </goals> </execution> </executions>
        <configuration> <revisionOnScmFailure>true</revisionOnScmFailure> <format>{0}-{1,date,yyyyMMdd}</format> <items> <item>${project.version}</item> <item>timestamp</item> </items> </configuration>
    </plugin>
</plugins>

В примере выше происходят три важные вещи. Во-первых, указан сам плагин для задания версии сборки. Во-вторых, указано, что он будет запускаться во время фазы validate (самая первая фаза) и генерировать номер сборки – ${buildNumber}.

И в-третьих, указан формат этого номера сборки, который склеивается из нескольких частей. Это версия проекта project.version и текущее время заданное шаблоном. Формат шаблона задается Java-классом MessageFormat.

Комментарии (28)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Даниил Уровень 79
30 июня 2025
В данном предложение есть дублирование. Да, вы можете размещать библиотеки внутри другой библиотеки. И вас ждет много сюрпризов, когда вам нужно будет куда-то передать путь к properties-файлу, который находится в jar-библиотеке, которая находится в jar-библиотеке.
Nicko Уровень 2
11 сентября 2024
Если это прочесть до конца, дойти до проекта в конце уровня, и выполняя проект вернуться и перечитать это еще раз, то произойдет магия и станет понятно больше!
Олег Уровень 106 Expert
31 июля 2024
Просто читаю, а запомнить не могу.
Никита Уровень 88
28 января 2024
какой зависимостью подключить com.javarush.engine.cell.*;?
Андрей Пазюк Уровень 122 Expert
26 марта 2024
Никита, эту зависимость нужно указать для подключения. <dependency> <groupId>com.javarush</groupId> <artifactId>desktop-game-engine</artifactId> <version>1.0</version> </dependency> Но она не сработает вот так сразу, потому что ее нету в облачном репозитории. Ее нужно установить в локальный Maven репозиторий командой: mvn install:install-file -Dfile=D:\Projects\Java\project-maven\lib\desktop-game-engine.jar -DgroupId="com.javarush" -DartifactId=desktop-game-engine -Dversion="1.0" -Dpackaging=jar Но сначала нужно подставить ваш правильный путь к самому jar файлу, потому что в команде указан мой путь. Сам файл находится уже в проекте, в папке "lib".
Андрей Уровень 37 Expert
13 июля 2024
Можно прямо dependency прописать:

<dependency>
       <groupId>com.javarush</groupId>
       <artifactId>desktop-game-engine</artifactId>
       <version>1.0</version>
      <scope>system</scope>
    <systemPath>D:\Projects\Java\project-maven\lib\desktop-game-engine.jar</systemPath>
</dependency>
Anonymous #3322801 Уровень 2 Expert
20 июля 2023
Небольшое обновление: Также обратите внимание, что в настоящее время source настройкой по умолчанию является 1.8, а target настройкой по умолчанию является 1.8 независимо от JDK, с которым вы запускаете Maven. proof
Даниил Уровень 92 Expert
5 июля 2023
Хорошее описание конфигурации плагинов и тегов для конфигурации плагинов можно посмотреть здесь - https://www.codetab.org/tutorial/apache-maven/plugins/maven-plugin-configuration/
Anonymous #3268884 Уровень 24
21 марта 2024
ага, четкая статья
Олег Уровень 111 Expert
29 июня 2023
В представленном фрагменте кода <configuration>: <compilerArgs> <arg>-verbose</arg> <arg>-Xlint:all,-options,-path</arg> </compilerArgs> <compilerArgs> определяет аргументы компилятора, которые будут использоваться при компиляции проекта: <arg>-verbose</arg> включает подробный вывод компилятора, что означает, что во время компиляции будут отображаться дополнительные сведения, такие как классы, которые компилируются, и информация о зависимостях. <arg>-Xlint:all,-options,-path</arg> включает все предупреждения о потенциальных проблемах в коде и исключает предупреждения, связанные с опциями (-options) и путями (-path). Таким образом, компилятор будет проверять код на наличие возможных проблем и выводить соответствующие предупреждения.
jvatechs Уровень 111 Expert
6 мая 2023
Во-вторых, каждая jar-библиотека должна иметь манифест (файл MANIFEST.MF). Плагин сам положит его в нужное место библиотеки, вам всего лишь нужно указать, по какому пути его взять. Вот не могу понять: если плагин сам положит его в нужное место, то и с этого места его надо будет и брать. Зачем мне еще указывать "по какому пути его взять"?
Ольга Николенко Уровень 109 Expert
1 февраля 2024
в случае если вы используете свой готовый файл manifest.mf компилятор не знает где вы его храните, вы задаете путь к файлу с помощью тега <manifestFile>, а уже при сборке компилятор положит его в нужное место если вы настраиваете генерацию файла MANIFEST.MF с помощью тега <manifest> - компилятор сам сразу создаст его в нужном месте, соответственно и путь к файлу указывать не нужно
Anonymous #3268884 Уровень 24
24 марта 2024
Суть в том, что есть два манифест-файла. Один исходный, а второй - сгенерированный. Тот файл, который плагин сам положит в нужное место библиотеки - это сгенерированный. Он создается плагином и кладется в нужное место, а именно в папку META-INF , которая тоже создается плагином внутри создаваемого джар-архива. Так вот, сгенерированный манифест можно создать двумя способами: либо на основе исходного манифеста, либо на основе мэйн-класса. Если создавать на основе исходного манифеста, то нужно написать тег <manifestFile>, и в этом теге указать, где лежит исходный манифест. А если создавать на основе мэйн класса, то нужно написать другой тег - <manifest>, и в нем указать, где лежит мэйн класс.
Денис Уровень 19
20 марта 2023
Мало что понятно...
Владимир Уровень 108
9 февраля 2023
для чего нужен MANIFEST.MF? Я упустил описание или его еще не было?
jvatechs Уровень 111 Expert
6 мая 2023
В контексте Maven проектов, файл MANIFEST.MF обычно генерируется автоматически при сборке приложения с использованием плагина Maven-Jar. Этот плагин может включать в MANIFEST.MF информацию о зависимостях проекта, основные классы приложения и другие настройки. MANIFEST.MF имеет важное значение при создании исполняемого JAR-файла, так как он содержит информацию, необходимую для запуска приложения из JAR-файла. Например, он определяет, какой класс является точкой входа для приложения, что позволяет запустить его с помощью команды java -jar. Кроме того, MANIFEST.MF может содержать пользовательские атрибуты и настройки, которые могут быть использованы во время выполнения приложения. В целом, MANIFEST.MF в Maven-приложениях служит для хранения метаинформации, необходимой для правильной сборки, упаковки и запуска приложения.