Maven
Li Wei
Maven
Overview
What is MVN?
Maven is essentially a project management tool that abstracts the development and management process into a Project Object Model (POM).
POM: Project Object Model. Maven is written in Java and manages everything in an object‑oriented way, ultimately treating a project as an object called a POM.
pom.xml: Maven requires a pom.xml file. By loading this configuration file, Maven can learn the project's information; the file represents a single project. If you have eight projects, you will have eight pom.xml files.
Dependency management: Maven manages all the resources a project depends on. The relationship is bidirectional: a project can declare the resources it needs, and when other projects depend on yours, Maven also treats your project as a managed resource.
Storage locations for managed resources: local repository, private repository, central repository.
Main functions:
- Project building: Provides a standard, cross‑platform way to automate builds.
- Dependency management: Conveniently manages project dependencies (JAR files) and avoids version conflicts.
- Unified development structure: Supplies a standard, consistent project layout.
Directory purpose summary:
src/main/java: Java source code.src/main/resources: Configuration files (e.g., MyBatis configs, XML mappers, custom config files).src/main/webapp: Web resources (HTML, CSS, JS, etc.).src/test/java: Test code.src/test/resources: Test‑related configuration files.src/pom.xml: Project’s POM file.
Core Concepts
Repository: Stores resources, mainly JARs. Types include local repository, private repository, and central repository (the latter two are remote).
- Central repository: Maintained by the Maven team; it is open source.
- Private repository: Used within a company/department to store resources. It can also proxy the central repository. Purposes:
- Store copyrighted resources (purchased or internally developed JARs).
- Share resources internally while keeping them private externally.
- Local repository: Resides on a developer’s machine; can also fetch resources from remote repositories.
Coordinates: In Maven, coordinates describe the location of a resource in a repository.
- Purpose: Provide a unique identifier so that machines can locate and download the resource automatically.
- Lookup: Use https://mvnrepository.com to search for a resource’s coordinates by name.
- Dependency elements:
groupId: The organization or domain (usually reversed, e.g.,org.mybatis).artifactId: The name of the resource (often the project or module name, e.g.,crm,sms).version: The resource’s version.packaging: How the resource is packaged; common values:jar(Java Archive) – default.war(Web Application Archive).pom– indicates a parent POM (used for multi‑module projects); only apom.xmlis generated, no JAR or other package.
Environment Setup
Configuration
Maven website: http://maven.apache.org/
Directory layout:
bin: Executable programs.boot: Maven’s own bootstrap loader.conf: Maven configuration files.lib: Libraries required for Maven runtime.
Set MAVEN_HOME:
Add to Path: %MAVEN_HOME%\bin
After configuring environment variables, test the setup by running the following command in a DOS window: mvn -v
Repository Configuration
By default, Maven’s local repository is located at .m2/repository in the user’s home directory. To change its location, edit Maven’s settings file conf/settings.xml.
Change local repository location: Find the
<localRepository>tag and modify its default value.
Note: Asettings.xmlfile should also exist in the same directory as the repository (.m2) – local user settings take precedence over global settings.Global
settings.xmldefines Maven’s common configuration.User
settings.xmldefines the current user’s configuration.Change remote repositories: Locate the
<mirrors>tag in the settings file and add a domestic mirror under it.Change default JDK: Find the
<java>tag and add the appropriate configuration.
Project Creation
Manual Setup
Create a Maven project directory
project-javaand navigate into it.Create the Java source directory:
src/main/java.Create the configuration files directory:
src/main/resources.Create the test source directory:
src/test/java.Create the test resources directory:
src/test/resources.In
src/main/javacreate a package (on Windows this means creating a folder)demo, and inside it create the fileDemo.javacontaining the demo Java program shown below.In
src/test/javacreate a test package (folder)demo, and inside it add the test programDemoTest.java.In
**project-java/src**create**pom.xml**file with the following format:After the structure is ready, build the project with Maven. Maven commands start with
mvn; additional goals are added as space‑separated parameters, allowing multiple goals to run in one line.mvn compile– compilemvn clean– cleanmvn test– testmvn package– packagemvn install– install to the local repository
Note: Running any goal will also execute all preceding goals.
IDEA Setup
Without Archetype
- Configure Maven in IDEA, selecting Maven 3.6.1 to avoid dependency issues.
- Create a Maven project: New Module → Maven → leave Create from archetype unchecked.
- Fill in the project coordinates:
GroupId:demoArtifactId:project-java
- Verify that directory colors are correct.
- In IDEA’s right‑hand panel, open Maven Project → Lifecycle.
- Add custom Maven commands: Run → Edit Configurations → click + → Maven.
Using an Archetype
Standard project:
- When creating a Maven project, choose an archetype (template).
- After creation, some directories may be missing; add them manually and mark them appropriately.
Web project:
Choose a web‑related archetype (those starting with “Maven” are simplified).
The generated structure will be incomplete; add the missing directories and mark them correctly.
To run the web project, add the Tomcat plugin coordinates in
pom.xml:- After configuring the plugin, you’ll see it in IDEA’s right‑hand panel
maven-projectand can start the project viaweb01 → Plugins → tomcat7 → tomcat7:run.
- After configuring the plugin, you’ll see it in IDEA’s right‑hand panel
Dependency Management
Declaring Dependencies
A dependency is a JAR required at runtime. The declaration format is:
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<!-- optional: <scope>...</scope> -->
</dependency>
Transitive Dependencies
Dependencies are transitive and fall into two categories:
- Direct dependencies: Declared explicitly in the current project.
- Indirect (transitive) dependencies: Dependencies of your dependencies.
Conflict resolution rules (when transitive dependencies clash):
- Nearest‑first (path priority): The deeper the dependency in the tree, the lower its priority.
- Declaration order: When at the same depth, the earlier declaration wins.
- Special priority: When the same version is declared at the same level, the later declaration overrides the earlier one.
- Optional dependency: Hides the dependency from downstream projects (non‑transparent).
- Exclusion: Actively removes a transitive dependency; no version needs to be specified.
Dependency Scope
By default, a JAR is available everywhere. The <scope> tag (scope) can limit its visibility:
- compile – available in the main source (
src/main). - test – available only in test source (
src/test). - provided – needed for compilation but not packaged.
- runtime – needed at runtime but not for compilation.
The <scope> tag accepts four values: compile,test,provided,runtime.
Scope transitivity: (details omitted in source)
Build Lifecycle
Key Phases
Maven’s build lifecycle describes the sequence of phases a build goes through. The most common flow:
compile → test-compile → test → package → install
clean: Cleanup work.
pre-clean: Tasks before cleaning.clean: Remove all files from the previous build.post-clean: Tasks immediately after cleaning.
default: Core work (compile, test, package, deploy, etc.). Each phase automatically runs all preceding phases.
site: Generate reports and publish a site.
pre-site: Tasks before site generation.site: Generate the project site.post-site: Tasks after site generation, preparing for deployment.site-deploy: Deploy the generated site to a server.
Executing Phases
Maven plugins are bound to lifecycle phases. When a phase is reached, the associated plugin runs. Maven ships with default plugins bound to each phase, and you can add custom plugins as needed.
Module Development
Splitting
Dividing a project into modules:
ssm_pojo
- Create a new module and copy the original project’s POJO classes (e.g.,
User). No configuration files needed.
- Create a new module and copy the original project’s POJO classes (e.g.,
ssm_dao
- Create a new module and copy data‑layer interfaces (e.g.,
UserDao) and related config files (3 files). Keep the pagination plugin configuration tied toSqlSessionFactoryBean. Thepom.xmlshould only include data‑layer dependencies (remove Spring MVC ones). - Dependencies: directly depend on
ssm_pojo(runinstallonssm_pojoto put it in the local repo).
- Create a new module and copy data‑layer interfaces (e.g.,
ssm_service
- Create a new module and copy service interfaces/implementations (e.g.,
UserService,UserServiceImpl) and one data‑layer config file.pom.xmlshould include data‑layer dependencies (remove Spring MVC). - Dependencies: directly depend on
ssm_dao(install it locally) and indirectly onssm_pojo(viassm_dao). - Rename the Spring core config file to include the module name, e.g.,
applicationContext-service.xml.
- Create a new module and copy service interfaces/implementations (e.g.,
ssm_controller (web layer)
- Create a new module using the
webapptemplate and copy controller classes (e.g.,UserController) and related config files (1 presentation‑layer config, 1 server config). pom.xmlshould include only web‑related dependencies (remove Spring MVC from previous modules).- Dependencies: directly depend on
ssm_service(install it locally) and indirectly onssm_daoandssm_pojo. - Update
web.xmlto load all Spring contexts using the*wildcard (loads any file starting withapplicationContext-). - Add the Spring MVC dependency.
- Create a new module using the
Aggregation
Purpose: Quickly build a Maven project that consists of multiple modules in one go.
How to create:
- Create an empty module with packaging type
pom. - List the modules to be built together under
<modules>.
Note: Execution order of aggregated modules depends on their inter‑module dependencies, not on the order they appear in the POM.
Inheritance
Maven inheritance works like Java inheritance: a child module can reuse configuration from a parent.
dependencyManagementonly declares dependencies; child modules must explicitly list the dependencies they need.- If a child does not declare a dependency, it will not inherit it.
- If a child declares a dependency without a version, the version (and scope) are inherited from the parent.
- If the child specifies a version, that version overrides the parent’s.
How to set up:
- In the child module, declare the parent’s coordinates and relative path.
- Define managed dependencies in the parent’s
dependencyManagement. - In the child, declare dependencies without versions; they will be resolved from the parent.
Inheritance vs. Aggregation:
Purpose
- Aggregation: Build multiple projects together quickly.
- Inheritance: Share configuration quickly.
Similarity
- Both use a
pompackaging type and can be combined in a single POM. - Both are design‑time constructs; they contain no actual code.
- Both use a
Differences
- Aggregation is defined in the current module and knows which modules participate.
- Inheritance is defined in the child; the parent does not know which children inherit from it.
Properties
Keeping versions consistent is crucial.
Property categories:
- Custom properties
- Built‑in properties
- Settings properties
- Java system properties
- Environment variable properties
Custom properties
- Purpose: Define variables for centralized maintenance.
- Format:
<properties>
<my.property>value</my.property>
</properties>
- Usage:
${my.property}
Built‑in properties
- Purpose: Use Maven’s predefined properties for quick configuration.
- Usage:
${project.version},${java.version}, etc.
Settings properties
- Pulled from
settings.xmltags; useful for dynamic configuration. - Usage:
${settings.localRepository}, etc.
Java system properties
- Purpose: Read Java system properties.
- Usage:
${java.home}, etc. - Query via command line:
cmd /c "echo %JAVA_HOME%"
Environment variable properties
- Purpose: Use environment variables.
- Usage:
${env.PATH}, etc. - Query via command line:
echo %PATH%
Project Versions
SNAPSHOT (development version):
- Used during active development to allow team members to share and update modules frequently.
- SNAPSHOT versions are continuously updated as development progresses.
RELEASE (stable version):
- After reaching a milestone, a stable version is released. The artifact is immutable; further development does not alter this released version.
Versioning convention:
- Major: Significant architectural changes (e.g., Spring 5 vs. Spring 4).
- Minor: Large feature additions or systematic bug fixes.
- Patch: Minor bug fixes.
- Milestone: Pre‑release version indicating an internal checkpoint; less stable than the subsequent official release.
Resource Filtering
Purpose: Load properties defined in the POM into any configuration file.
- Parent POM:
pom.xml - Enable filtering in the build section and reference properties in resource files using
${property.name}.
Multi‑Environment Configuration
Load environment‑specific settings:
- Define profiles in
pom.xmlfor each environment. - Activate a profile to load its configuration.
- Example usage:
mvn clean install -Pdev
Skipping Tests
Command:
mvn install -DskipTests
Note: The command’s lifecycle must still include the test phase for the flag to have effect.
IDEA interface: (screenshot placeholder)
Configure skipping in the IDE settings as needed.
Maven Private Repository
Nexus
Nexus is a Maven repository manager from Sonatype.
Download: https://help.sonatype.com/repom
(content truncated)
Originally written by Li Wei (李唯_) and published in Chinese on 后端技术栈全书 (Full-Stack Backend Engineering). Translated and adapted for DriftSeas with permission.