Основы использования Maven

Maven строит проект из декларативной модели pom.xml: coordinates, dependencies, plugins, repositories и lifecycle. Хороший проект одинаково собирается через wrapper в терминале и CI.

Coordinates

<groupId>com.example</groupId>
<artifactId>demo-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

groupId:artifactId:version идентифицирует artifact. Dependency сначала ищется в local repository, затем в настроенных remote repositories.

Lifecycle

Основные фазы default lifecycle:

validate → compile → test → package → verify → install → deploy

Вызов поздней фазы выполняет предыдущие. mvn package не делает install; install кладёт artifact в local repository, deploy публикует в remote.

clean — отдельный lifecycle, поэтому обычно вызывают:

./mvnw clean verify

Dependencies и scopes

ScopeCompileTestRuntime artifact
compileдадада
providedдаданет
runtimeнетдада
testнетданет

Transitive dependency выбирается по mediation rules. Чтобы увидеть реальное дерево:

./mvnw dependency:tree
./mvnw help:effective-pom
./mvnw help:active-profiles

Исключение transitive dependency не добавляет нужную версию автоматически — её объявляют явно или управляют через dependencyManagement.

Plugin и dependency — не одно

Dependency попадает в classpath приложения. Plugin выполняет шаг сборки: compiler, tests, packaging, code generation.

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <release>21</release>
      </configuration>
    </plugin>
  </plugins>
</build>

Воспроизводимость

  • wrapper фиксирует Maven runtime для команды;
  • версии plugins задаются явно или parent/BOM;
  • snapshot зависимости не подходят для воспроизводимого release;
  • secrets не хранятся в pom.xml;
  • CI сохраняет artifact, созданный проверенной сборкой, а не пересобирает перед deploy.

Полезные команды

./mvnw -q test
./mvnw clean verify
./mvnw -Dtest=OrderServiceTest test
./mvnw versions:display-dependency-updates

-DskipTests обычно не запускает tests, но компилирует test sources; -Dmaven.test.skip=true пропускает и компиляцию. В release pipeline это осознанное исключение, не shortcut по умолчанию.

Типичные сбои

  • IDE использует один JDK, Maven — другой.
  • Dependency присутствует transitively и исчезает после обновления соседней library.
  • Profile неявно активируется только на машине разработчика.
  • Artifact публикуется до verify.
  • Две версии logging backend попадают через разные ветви dependency tree.

Вопросы для собеседования

Чем package отличается от install? Первая создаёт artifact в target, вторая дополнительно кладёт его в local repository.

Что делает dependencyManagement? Управляет версиями/настройками, но само по себе обычно не добавляет dependency в модуль.

Чем plugin отличается от dependency? Plugin исполняет build goal, dependency входит в classpath проекта.

Зачем effective-pom? Увидеть итоговую модель после inheritance, profiles и defaults.

Почему wrapper полезен? Даёт команде и CI согласованную версию Maven.

См. Артефакт, Jar файл Java, IntelliJ IDEA.