Master Maven Dependencies, Lifecycle, and Plugins for Efficient Java Projects
This article explains how to manage Maven dependencies, understand transitive, optional, and excluded dependencies, configure dependency scopes, navigate the Maven build lifecycle, use plugins, and set up module aggregation, inheritance, properties, versioning, environment profiles, and a private Nexus repository for Java projects.
Dependencies
Maven dependencies are declared in the
dependenciestag, allowing automatic download of required JARs from remote repositories without manual handling.
<code><dependencies>
<!-- servlet package -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies></code>After adding a dependency, refresh Maven to fetch the corresponding JAR files.
Transitive Dependencies
Dependencies are transitive: adding one brings in all of its own dependencies. For example, adding
druid-spring-boot-starterautomatically pulls in several indirect dependencies, as shown in the diagram. When direct and transitive versions conflict, Maven resolves them by giving higher priority to the outermost declaration; if at the same level, the earlier declaration wins.
Optional Dependencies
Optional dependencies hide transitive resources from downstream consumers. Setting
optionalto
truedisables the indirect dependencies.
<code><dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<optional>true</optional>
</dependency></code>Excluding Dependencies
Exclusions actively cut off transitive dependencies. The following example excludes
hamcrest-corefrom the JUnit dependency.
<code><dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency></code>Optional dependencies are defined by the dependency provider, while exclusions are configured by the consumer.
Dependency Scope
The
scopetag limits where a JAR is used (e.g.,
compile,
test,
provided,
runtime). The diagram illustrates the effect on main code, test code, and packaging.
Lifecycle and Plugins
Project Build Lifecycle
Maven defines three lifecycle phases: clean (cleanup), default (core tasks such as compile, test, package, deploy), and site (report generation). The default phase is illustrated with a detailed diagram.
Plugins
Plugins are defined under
build→
pluginsand bind custom goals to specific lifecycle phases. The example adds the Maven Compiler Plugin with Java 1.8 source and target settings.
<code><build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build></code>Plugins execute when their bound phase runs. Typical plugin benefits include extending Maven with custom actions.
Plugin bound to lifecycle phase – executes at the designated phase.
Default Maven bindings provide common functionality.
Custom plugins enable additional tasks.
<code><build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build></code>Module Aggregation
Aggregating multiple modules enables a single build that processes all listed projects. The Ruoyi example lists modules such as
ruoyi-admin,
ruoyi-framework, etc., and sets
packagingto
pomfor the parent.
Module Inheritance
Inheritance shares configuration from a parent POM to child modules, avoiding duplicate version declarations. Example parent declaration and a
dependencyManagementsection are shown.
<code><parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.8.1</version>
</parent></code> <code><dependencyManagement>
<dependencies>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.5.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Alibaba Druid pool -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- MyBatis Spring Boot starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement></code>Properties
Maven supports several property types: custom, built‑in, settings, Java system, and environment variables. Examples demonstrate defining a custom property and referencing it, as well as using built‑in properties like
${basedir}and
${version}.
<code><properties>
<ruoyi.version>3.8.1</ruoyi.version>
</properties>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>${ruoyi.version}</version></code> <code>${basedir}
${version}</code>Version Management
Project version numbers are defined in the
versionelement of the POM and follow conventional patterns, as illustrated by screenshots of version listings.
Environment Configuration
Different environments (development, test, production) are handled via Maven profiles. The IDE shows profile selection, and the
application.ymlcan be adjusted based on the active profile.
Private Repository (Nexus)
Nexus provides a hosted Maven repository for internal artifacts. The article walks through creating a Maven2 hosted repository, adding it to a repository group, and configuring
settings.xmlwith server credentials, profiles, and distribution management for deployment.
<code><servers>
<server>
<id>ticknet-release</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>ticknet-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
</servers></code> <code><profiles>
<profile>
<id>artifactory</id>
<repositories>
<repository>
<snapshots><enabled>false</enabled></snapshots>
<id>repo</id>
<name>repo</name>
<url>xxxx</url>
</repository>
<repository>
<snapshots/>
<id>snapshots</id>
<name>snapshots-only</name>
<url>xxxx</url>
</repository>
</repositories>
</profile>
</profiles></code> <code><distributionManagement>
<repository>
<id>ticknet-release</id>
<url>http://localhost:8081/repository/ticknet-release/</url>
</repository>
<snapshotRepository>
<id>ticknet-snapshots</id>
<url>http://localhost:8081/repository/ticknet-release/</url>
</snapshotRepository>
</distributionManagement></code>Running the
deployphase uploads artifacts to the configured Nexus repository.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.