Перейти к содержанию
Educora
Продвинутый20 мин13 / 18

Maven и Gradle: сборка проекта

Узнай стандартную структуру настоящего Java-проекта, как объявлять зависимости в `pom.xml` и `build.gradle.kts` и как устроен жизненный цикл Maven.

Проверь себя
В этом уроке ты узнаешь
  • Узнавать стандартную структуру папок проекта Maven/Gradle
  • Добавлять зависимость по координатам (groupId:artifactId:version) с правильной областью (scope)
  • Запускать фазы жизненного цикла Maven и задачи Gradle

До сих пор каждая программа была одним файлом Main.java, который запускался командой java Main.java. В настоящем проекте — сотни классов, десятки внешних библиотек (JSON, драйвер базы данных, фреймворк для тестов) и несколько разработчиков. Скачивать каждый JAR-файл вручную и передавать javac длинный список -cp быстро становится кошмаром. Эту работу выполняют системы сборки (build tools): Maven и Gradle сами скачивают библиотеки, компилируют код, запускают тесты и упаковывают готовый JAR-файл.

Стандартная структура проекта

Maven следует принципу «соглашения важнее конфигурации» (convention over configuration): файлы всегда лежат в одних и тех же местах, поэтому не нужно объяснять инструменту, где их искать. Gradle использует ту же структуру. Основной код находится в src/main/java, тесты — в src/test/java, а файлы настроек и изображения — в src/main/resources. Имя пакета превращается в папки: пакет com.educora — это папка com/educora. Результат сборки попадает в target/ у Maven и в build/ у Gradle.

Text
grade-book/
├── pom.xml                  ← Maven (Gradle: build.gradle.kts)
├── src/
│   ├── main/
│   │   ├── java/com/educora/App.java
│   │   └── resources/config.properties
│   └── test/
│       └── java/com/educora/AppTest.java
└── target/                  ← build output (Gradle: build/)
Типичная структура проекта Maven или Gradle
Определение
Зависимость (dependency)

Внешняя библиотека, без которой проект не работает. Её определяют три координаты: groupId (организация, например com.google.code.gson), artifactId (имя библиотеки, gson) и version (2.11.0). Краткая запись: com.google.code.gson:gson:2.11.0. Инструмент скачивает библиотеку из репозитория Maven Central и хранит её в кэше на компьютере.

Maven и pom.xml

Сердце проекта Maven — файл **pom.xml (Project Object Model). В нём записаны координаты самого проекта, версия Java и список зависимостей. В файле ниже две зависимости: Gson для работы с JSON и JUnit для тестов. Библиотеки, которые нужны им самим, — транзитивные зависимости** — Maven скачивает автоматически.

XML
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.educora</groupId>
  <artifactId>grade-book</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

  <properties>
    <maven.compiler.release>21</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.11.0</version>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.11.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
pom.xml: maven.compiler.release задаёт компиляцию под Java 21

Обрати внимание на строку <scope>test</scope>: JUnit нужен только в тестах и не должен попасть в готовую программу. Область (scope) определяет, где можно использовать зависимость:

ScopeГде виднаПример
compileвезде: основной код, тесты и работающая программа (по умолчанию)Gson
testтолько в src/test/javaJUnit, Mockito
providedпри компиляции; во время работы её даёт серверServlet API
runtimeтолько во время работы, не при компиляциидрайвер JDBC

Жизненный цикл Maven

В Maven команды — это фазы жизненного цикла, которые идут в строгом порядке. Вызывая фазу, Maven выполняет и все фазы перед ней: mvn package сначала проверяет проект, компилирует его и запускает тесты, и только потом создаёт JAR. Если хоть один тест упал, сборка останавливается — код с ошибкой не упаковывается. clean — отдельная фаза: она удаляет старую папку target/.

ФазаЧто делает
validateпроверяет корректность проекта
compileкомпилирует src/main/java в target/classes
testзапускает тесты из src/test/java
packageсоздаёт JAR- (или WAR-) файл
verifyвыполняет дополнительные проверки, например интеграционные тесты
installкладёт JAR в локальный репозиторий (~/.m2)
deployотправляет JAR в удалённый репозиторий команды
Terminal
mvn clean package
Ожидаемый результат
[INFO] Scanning for projects...
[INFO] Building grade-book 1.0.0
[INFO] --- compiler:3.13.0:compile (default-compile) @ grade-book ---
[INFO] --- surefire:3.2.5:test (default-test) @ grade-book ---
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO] --- jar:3.4.1:jar (default-jar) @ grade-book ---
[INFO] Building jar: C:\projects\grade-book\target\grade-book-1.0.0.jar
[INFO] BUILD SUCCESS
Пример вывода (сокращён): версии плагинов и пути у тебя могут отличаться

Gradle и build.gradle.kts

Gradle делает ту же работу, но вместо XML использует скрипт, похожий на программный код. В современных проектах скрипт пишут на Kotlin — build.gradle.kts (в старых проектах встретится и build.gradle на Groovy). Вместо фаз у Gradle задачи (tasks): compileJava, test, jar, build. Gradle не пересобирает то, что не изменилось, и кэширует результаты, поэтому в больших проектах он обычно быстрее Maven. Android-приложения тоже собираются с помощью Gradle.

Kotlin
plugins {
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.google.code.gson:gson:2.11.0")
    testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

application {
    mainClass = "com.educora.App"
}

tasks.test { useJUnitPlatform() }
build.gradle.kts: implementation соответствует области compile в Maven, а testImplementation — области test

Плагин application добавляет задачу ./gradlew run: она запускает класс из mainClass вместе со всеми библиотеками. Блок toolchain велит Gradle собирать проект именно на Java 21. Сравни ручную сборку и Gradle:

Без инструмента: всё вручную
# download every JAR by hand into lib/, then:
javac -d out -cp lib/gson-2.11.0.jar src/com/educora/*.java
java -cp "out:lib/gson-2.11.0.jar" com.educora.App
# a new library? download it, fix both commands again...
Gradle: две короткие команды
# dependencies are listed once in build.gradle.kts
./gradlew build   # download, compile, test, package
./gradlew run     # start the app with all its libraries
ДействиеMavenGradle
Компиляцияmvn compile./gradlew compileJava
Запуск тестовmvn test./gradlew test
Сборка JARmvn package./gradlew build
Удаление результатов сборкиmvn clean./gradlew clean
Дерево зависимостейmvn dependency:tree./gradlew dependencies

Создай проект шаг за шагом

  1. 1
    Проверь JDK

    Набери в терминале java -version: версия должна быть 21 или новее.

  2. 2
    Создай проект

    В IntelliJ IDEA выбери File › New › Project: язык Java, Build system — Maven или Gradle, JDK 21. Впиши com.educora в поле GroupId и grade-book в поле ArtifactId. В терминале то же самое делает команда gradle init.

  3. 3
    Добавь зависимость

    Найди координаты библиотеки на сайте Maven Central и впиши их в pom.xml или build.gradle.kts. Затем нажми Reload в панели Maven/Gradle в IDE, чтобы библиотека скачалась.

  4. 4
    Собери и запусти

    mvn package или ./gradlew build запустит тесты и создаст JAR; в Gradle ./gradlew run сразу запускает программу. Готовый JAR окажется в target/ или build/libs/.

Главное

  • Maven и Gradle скачивают библиотеки, компилируют код, запускают тесты и собирают JAR.
  • Стандартная структура: src/main/java, src/main/resources, src/test/java; результат — в target/ или build/.
  • Зависимость записывается координатами groupId:artifactId:version; её область (scope) определяет, где она видна.
  • При вызове фазы Maven выполняются и все предыдущие: package = validate → compile → test → package.
  • В Gradle пишут implementation / testImplementation; wrapper (./gradlew, ./mvnw) даёт всем одну и ту же версию.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
В какую папку проекта Maven кладут тестовые классы?