Skip to content
JackSparrow414
Go back

Learning and Understanding Maven in Depth

Table of contents

Open Table of contents

Learning and Understanding Maven

Install Maven

Download from the Official Website

On the download page, choose a file under Files. Usually, select Binary zip archive.

Install on a Mac

On macOS, install Maven with Homebrew.

brew update
brew search maven
# Choose the version to install
brew install maven

Installation

The official installation guide covers Windows and macOS. It mainly involves configuring environment variables for the machine.

Verify the Installation

mvn -v

If the command prints the Maven version, installation path, and Java version, installation succeeded.

This also shows that Maven depends on Java. Maven is written in Java; if that is unfamiliar, the Configuring Apache Maven documentation also contains a statement confirming it.

This variable contains parameters used to start up the JVM running Maven

How Do We Select the Java Version Used by Maven?

Change the JAVA_HOME environment variable.

How Do We Set JVM Options for Maven?

Use the MAVEN_OPTS environment variable.

Configure Maven in an IDE

See here for Eclipse and IntelliJ IDEA configuration instructions.

Quickly Create a Maven Project and Understand Its Standard Structure

  1. Generate a Maven project scaffold.

    mvn -B archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

    The command generates a Maven project in a directory named my-app.

  2. A standard Maven project has this structure: Standard project directory layout listed in the Maven documentation

    See the standard directory layout documentation. Not every directory shown is required, but the main ones should be present: src/main/java, src/main/resources, src/test/java, src/test/resources, and pom.xml.

    In an ordinary Maven project, pom.xml and src are at the same directory level.

Maven Lifecycles

The long command above generated a basic project. What does each part mean? First, we need to understand Maven’s overall structure.

A Common Scenario

When starting with Maven—or mainly adding dependencies at work—we sometimes need to configure a plugin or perform extra operations during packaging. Without understanding Maven’s structure, the process usually looks like this:

This wastes time, and learning isolated fragments does not help us solve problems thoroughly. The next similar scenario sends us back to searching instead of applying what we have learned.

Lifecycles

A lifecycle is Maven’s highest-level unit of organization.

Complete lifecycle documentation

Maven has three lifecycles: default, clean, and site. Most everyday project work uses default; we rarely use site. The key point is that lifecycles form the top level.

Phases

A lifecycle comprises many phases.

For example, the default lifecycle has seven major phases:

These phases execute in sequence. Even when you request only install, all preceding phases must run before it. Maven documentation describing build lifecycle phases and sequential execution

Why say seven major phases? The full default lifecycle has many more, but these are representative. See the complete lifecycle reference.

Execute a Phase

Maven’s structure is lifecycle → phase, and its commands follow that organization.

The format is:

mvn PHASE (mvn followed by the phase to execute through)

You can specify several phases, such as mvn clean package. Here, clean belongs to the clean lifecycle and package to the default lifecycle. Maven identifies the lifecycle from each phase. The lifecycle reference above lists all phases.

# Follow mvn with the phase to execute through
mvn package

Phases and Goals

A lifecycle is the highest level, followed by phases. Phases are the basic units used when invoking lifecycle commands. Each phase has corresponding goals, which specify the actual work to perform.

Who implements those goals? Rather than Maven itself, plugins do the work. Maven has a rich collection of plugins implementing goals for different phases.

At the level of actual execution, the basic unit therefore becomes the goal.

The format is:

mvn PLUGIN_NAME:GOAL

mvn Plugin:goal

Why do common commands such as mvn package and mvn install not use this format?

Some lifecycle phases have default plugin-goal bindings, so those goals need not be written explicitly. See the official documentation.

For example, mvn package is effectively mvn jar:jar.

Similarly, mvn install is effectively mvn install:install. Maven lifecycle-to-plugin goal bindings for different packaging types

Maven Plugins

During execution, Maven uses plugins to run the corresponding goals. See the plugin list. Maven plugin list with explanations of build and reporting plugins

Its first sentence confirms that plugins perform Maven’s actual work. Plugins are usually configured under in pom.xml, although some are configured under .

Find a matching Description in the plugin list, then click the Plugin entry to open its documentation. It generally explains the phase in which the plugin runs and how to configure it.

A Plugin Example

At work, project JARs are usually compiled, built, packaged, and automatically published to the company’s private Maven repository. What if we want to publish a locally built JAR ourselves?

The requirement is to publish a JAR to a Maven repository.

Find a matching description in the plugin list. Maven Deploy Plugin page describing the deploy and deploy-file goals

Click deploy to open the plugin documentation. The deploy plugin description in the Maven plugin list This plugin runs in the default lifecycle’s deploy phase and publishes to remote repositories. It can also deploy third-party JARs and generate corresponding POM files.

It has two goals: deploy and deploy-file.

The Usage section on the left explains how to use them. Repository and server configuration requirements in Maven Deploy Plugin usage documentation The usage page describes the appropriate scenario for each goal. Usually, mvn deploy uses deploy:deploy. Configure the repository in pom.xml and the server in the global setting.xml file, then use mvn deploy to publish the POM to the remote repository.

deploy-file applies when a project was not built with Maven. A common case is a third-party JAR without a Maven POM that we need in a Maven project. Download the JAR and deploy it manually to the remote repository. A POM is generated by default, letting us reference the dependency in pom.xml.

mvn deploy:deploy-file -Durl=repositoryUrl -DrepositoryId=repositoryId -Dfile=my-app.jar -DgoupId=com.mycompany.app -DartifactId=my-app -Dversion=1.0
-Dpackaging=jar

url: the private Maven repository URL.

repositoryId: the private repository server ID.

file: the JAR’s location.

groupId, artifactId, and version are all required.

packaging: the package format.

A corresponding POM is generated by default. deploy:deploy-file parameter example for uploading a third-party JAR and generating a POM

Choose plugins according to the actual requirement. We cannot remember every plugin, so searching may still be necessary—but we only need to find its name, locate it in the plugin list, and follow its documentation. We need not rely on miscellaneous articles for the entire process. Many online posts are unreliable or copied from one another, wasting our time.

Configure Plugins in the POM: pluginManagement vs. plugins

The plugin configuration guide explains configuration, including specifying phases and goals inside execution.

Individual plugin documentation usually provides a default configuration. Most Maven plugins follow common configuration rules.

Plugins are generally configured under pluginManagement within , and each should have at least groupId, artifactId, and version.

For example, configure Surefire, which runs unit tests in the test phase.

<build>
    <pluginManagement>
      <plugins>
        <plugin>
          <!--Plugins must specify groupId, artifactId, and version-->
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
     <plugins>
        <plugin>
          <!--Plugins must specify groupId, artifactId, and version-->
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.2</version>
           <configuration>
            <skipTests>true</skipTests>
          </configuration>
        </plugin>
      </plugins>
  </build>

Some plugins need an executions section specifying which goal runs in which phase.

Note the distinction between and . pluginManagement is generally declared in the parent POM. A child declares the plugin in plugins without repeating its version. pluginManagement only declares the configuration; the plugin must still be included under plugins to be used.

If it is declared but not included, the plugin cannot be found.

Another common mistake is placing a plugin directly inside pluginManagement when trying to use it. The plugin is then unavailable.

POM example with the assembly plugin configured only under pluginManagement

For example, putting the assembly plugin directly in pluginManagement does not activate it. IntelliJ IDEA’s panel can help determine whether it is active. IDEA Maven plugin list without the assembly plugin

Although we configured it in pluginManagement, it does not appear under the IDE’s plugins, showing that the configuration has not taken effect.

Remove the pluginManagement wrapper or configure the plugin in a sibling plugins section. IDEA Maven plugin list showing the assembly plugin after configuration is corrected

This is the correct configuration.

How Do We Skip Unit Tests?

Generally, do not skip unit tests; they are important.

Surefire handles the unit tests. See its test-skipping configuration.


<properties>
  <skipTests>false</skipTests>
</properties>

<build>
   <plugins>
     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <version>2.22.2</version>
       <configuration>
         <skipTests>${skipTests}</skipTests>
       </configuration>
     </plugin>
   </plugins>
</build>

Commands:

Run unit tests:

mvn test

Skip unit tests:

# The property after -D is the custom skipTests property under properties in the POM; true is passed here
# The property name is configurable, so a Surefire test-skipping command depends on the property name in the POM
mvn -DskipTests=true

The second form:

# This skips both test compilation and execution. I do not recommend it: after code changes, some tests may not even start, and tests are generally required to pass. Skipping compilation entirely is undesirable
mvn -Dmaven.test.skip=true

Run Only Some Unit Tests

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.22.2</version>
    <configuration>
      <includes>
        <include>SimpleServletTest.java</include>
      </includes>
    </configuration>
</plugin>

See the inclusion and exclusion documentation.

POM Structure

pom:Project Object Model

So far, we have not configured a POM in detail. Once we understand lifecycles, phases, plugins, and goals—and that Maven delegates actual work to plugin goals—POM configuration becomes much easier.

Introduction to the POM

Basic Structure

Required POM elements:

<preject>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>
</preject>

The complete artifact coordinates are ::, here com.mycompany.app:my-app:1.

The default packaging type is jar. Maven Minimal POM documentation describing coordinates and default packaging A version containing SNAPSHOT is a development version whose reliability is not guaranteed. Projects should minimize these dependencies and use release versions.

Manage Dependency Versions

Official documentation

A POM may contain dozens or hundreds of dependencies, each with a version. Searching throughout it to change versions is inconvenient and makes the project’s dependencies harder to review. Versions are therefore generally collected near the top for easy inspection.

For example:

<properties>
  <fast.json.version>3.1.0</fast.json.version>
  <mysql.version>8.0.0</mysql.version>
</properties>

<dependencies>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fast.json</artifactId>
    <version>${fast.json.version}</version>
  </dependency>
</dependencies>

Put custom version properties inside .

properties can also receive property values passed through Maven command-line arguments.

For example:

mvn package -DskipTests=true

The argument after -D requires a property defined in properties.

The rules are:

Dependency Management: dependencyManagement vs. dependencies

See the dependency mechanism documentation.

A company may have many projects sharing dependencies such as the MySQL driver, Druid, and Spring Boot. For unified management, extract the shared dependencies into a parent POM used by all projects. Each project can add its other dependencies separately.

Why manage dependencies centrally? A few lessons from practice illustrate the reasons:

  1. If projects use different Spring Boot versions, later requirements may make previously unrelated projects communicate, particularly in a microservice environment. Version differences may cause project B to fail when using an API from project A. Standardizing versions at that point may break other parts of a project. Avoid this situation by aligning shared dependencies from the beginning, especially those used throughout the platform.
  2. Even without that problem, a private Maven repository must store many versions of a framework if different projects use different versions. This wastes storage and complicates cleanup: which versions can safely be removed? With many projects, nobody can easily guarantee that deleting one will not cause a problem. Unified dependencies leave one common framework POM, substantially reducing storage. A platform-wide upgrade then lets us remove the previous POM.

Example:

Define a shared POM to manage common dependencies.

parentPom.xml

<!--The parent POM has packaging type pom-->
<packaging>pom</packaging>

<properties>
  <fast.json.version>3.1.0</fast.json.version>
  <Druid.version>3.0.0</Druid.version>
  <!--...Other dependency version settings omitted-->
</properties>

<dependencyManagement>
  <dependencies>
     <groupId>com.alibaba</groupId>
     <artifactId>fast.json</artifactId>
     <version>${fast.json.version}</version>
  </dependencies>
  <!--...Other common dependencies omitted-->
</dependencyManagement>

  <dependencies>
     <groupId>com.alibaba</groupId>
     <artifactId>Druid</artifactId>
     <version>${Druid.version}</version>
  </dependencies>

Reference the parent POM’s dependencies when creating project A.

<project>
  <modelVerson>4.0.0</modelVerson>

  <!--Declare the parent POM in the child project-->
  <parent>
     <groupId>com.mycompany.myapp</groupId>
     <artifactId>my-parent</artifactId>
     <version>1.0.0</version>
  </parent>

  <!--Child project configuration-->
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>
</project>

The parent POM can declare dependencies inside dependencyManagement or directly under dependencies. What is the difference?

The distinction is:

Here are the parent dependencies. What does the child POM contain? IDEA showing the child module's inherited JUnit dependency without automatically adding fastjson

The parent has two dependencies, but Fastjson is under dependencyManagement, so the child only inherits JUnit by default, with the same version as the parent.

When the child includes Fastjson without a version, it inherits the parent’s version. Child POM using the parent-managed fastjson version without specifying a version When the child explicitly declares a dependency already inherited from the parent, it must specify a version; otherwise, an unknown error occurs. IDEA showing an unknown dependency error when its version is omitted in the child POM

What If Different Dependencies Bring Different Versions of the Same Library?

For example, framework A brings in Guava, while our project also declares Guava at a different version. Which version will be used? This is where exclusions inside dependency comes in.

When versions conflict, use exclusions to remove the dependency version we do not want.

Dependency Scopes

Official scope documentation

There are six scopes:

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.3.3.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
   </dependencies>

This lets us use both the parent POM’s dependencyManagement and Spring Boot’s dependencyManagement. You can look up the difference between spring-boot-dependencies and spring-boot-parent. They are essentially similar here; the choice depends on developer preference and the company’s Maven structure. If the common parent is not spring-boot-parent, spring-boot-dependencies may be used.

Inheritance and Aggregation

Official documentation

Inheritance means projects share a common parent POM.

Aggregation means a project comprises multiple modules.

The project in the screenshots uses both inheritance and aggregation.

Common Maven Requirements

How Do We Find Dependencies That Need Updating?

Dependencies need regular upgrades during maintenance. To identify updates, use versions-maven-plugin with the following custom rules.

<ruleset comparisonMethod="maven"
         xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 https://www.mojohaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
    <ignoreVersions>
        <ignoreVersion type="regex">.*[-_\.](alpha|Alpha|ALPHA|b|beta|Beta|BETA|rc|RC|M|EA)[-_\.]?[0-9]*</ignoreVersion>
    </ignoreVersions>
</ruleset>

How Do We Find Dependencies with Security Vulnerabilities?

Use dependency-check-maven.

Our approach is a scheduled Jenkins job that regularly runs both plugins against the latest main-branch code. They generate HTML reports, which are emailed to the people responsible for dependencies. This supports regular dependency maintenance and upgrades.

How Do We See Which JARs Changed After a Dependency Upgrade?

Specific people maintain most dependencies, but developers occasionally add or upgrade JARs while implementing features. They may not realize which other JARs change. Upgrading POI from 5.2.3 to 5.2.5, for example, changes not only POI but also its dependencies. Without informing developers or reviewers, this can introduce incompatible JARs or dependency conflicts.

Our approach: Pushing a branch triggers a Jenkins build. Its result is compared with the main-branch build using diff between the two workspaces, for example:

diff -rq /home/jenkins/.jenkins/workspace/main-branch/project-name/target/package/WEB-INF/lib /home/jenkins/.jenkins/workspace/develop-branch/project-name/target/package/WEB-INF/lib

Replace the following variables with values appropriate to your environment.

  1. main-branch
  2. package
  3. develop-branch

What Is mvnw? How Do We Pin a Project’s Maven Version?

Use the Maven Wrapper, mvnw.

When Should We Use Optional Dependencies?

Stack Overflow answer

How Do We Quickly Scaffold a Maven Project?

The initial project-creation example used a long command. Unless we use it daily, remembering every option for an occasional task is difficult. What can we do instead?

Maven performs its work through plugin:goal, so we only need to remember the scaffolding plugin.

The plugin is archetype.

Run its generate goal to create a project.

mvn archetype:generate

The command then prompts interactively.

It offers several project templates, including J2EE and Spring Boot. Enter the number of the desired template; the default is maven-archetype-quickstart. mvn archetype:generate interactive interface listing project templates

Next, enter groupId, artifactId, and version. Maven project generation prompts for groupId, artifactId, version, and package

Check the values and enter Y to confirm. The project is generated. Compared with the opening command, we only need mvn archetype:generate and the interactive prompts. Simple and convenient.

How Do We Quickly Scaffold a Multi-Module Maven Project?

The same idea applies to multiple modules: run the project-generation command several times.

Continue from the project created above:

How Can Profiles Select Different Modules for Different Environments?

Suppose a project has modules A, B, and C, but not all are always needed. A is required; local development also needs B, while testing needs B and C. How can we implement this?

Use Maven profiles in the root POM, as follows:

   <modules>
		<module>message-common</module>
   </modules>
   <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <modules>
                <module>business-server</module>
            </modules>
        </profile>
        <profile>
            <id>test</id>
            <modules>
                <module>message-server</module>
                <module>business-server</module>
            </modules>
        </profile>
    </profiles>

For the test environment, activate test with -P.

mvn clean install -Ptest

In IntelliJ IDEA, open Maven > Profiles and select the desired profile. Selecting the master profile under Profiles in the IDEA Maven panel

Profiles can also be combined with resource filtering below to replace file property values dynamically. See injecting Maven profile values into properties files.

How Do We Filter Resource Files or Replace ${value} with POM Properties During Packaging?

For including and excluding resources, see the Resources Plugin documentation.

Use maven-resources-plugin with filtering set to true to replace ${value} in selected files with POM properties during packaging. See the documentation for examples.

The official recommendation is to put files requiring filtering in a separate directory. Maven documentation recommending a separate directory for filtered resources

How Do We Skip Unit Tests?

Configure Surefire’s setting, define the corresponding property under properties, and pass that property on the command line.

mvn install -DskipTests=true

Can the JAR Produced by Maven’s Default Packaging Be Run with java -jar?

The JAR produced by the plugin goal bound to ordinary mvn package cannot be run with java -jar. Spring Boot is now common and typically uses its own packaging plugin; see the executable JAR documentation for details. Still, this distinction is worth explaining.

Run mvn package in the generated project, then try java -jar: java -jar error reporting no main manifest attribute in the JAR

It reports no main manifest attribute. What is that?

The JAR does not specify its runtime MainClass.

How Do We Build an Executable JAR or Fix “No Main Manifest Attribute”?

Use the Assembly Plugin.

Configure it as follows:

<build>
  <plugins>
     <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
<!--Include project dependencies in the JAR-->
            <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
<!--Specify the main class-->
              <manifest>
                <mainClass>com.mycompany.app.App</mainClass>
              </manifest>
            </archive>
          </configuration>
<!--Set the execution phase and goal-->
          <executions>
            <execution>
              <id>make-assembly</id>
              <phase>package</phase>
              <goals>
                <goal>single</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
  </plugins>
</build>

After configuration, run:

mvn package

This generates an XXX-jar-with-dependencies JAR.

java -jar child-one-1.0-SNAPSHOT-jar-with-dependencies.jar

It now runs successfully.

Inspect the JAR’s contents:

In META-INF/MANIFEST.MF: MANIFEST.MF with Main-Class configured as com.mycompany.app.App Main-Class is now specified, allowing the application to run.

How Do We Analyze Project Dependencies?

Use the official Dependency Plugin.

mvn dependency:tree -Dverbose

The command-line output clearly shows dependency conflicts. To check conflicts for a particular dependency, use:

mvn dependency:tree -Dincludes=org.apache.logging.log4j:log4j-api

Dependency-tree filtering documentation

If there are too many dependencies to inspect in the console, write the result to a file. For example, write it to the tmp directory on drive D.

mvn dependency:tree -Dverbose -Doutput=/d/tmp/file.txt -DoutputType=text

During everyday development, we usually use a graphical interface such as IntelliJ IDEA’s Maven Helper plugin. You can also open Dependencies in the Maven panel on the right in IntelliJ IDEA, as shown here:Opening the Maven dependency diagram in IDEA to inspect dependency relationships Thanks to this blogger for sharing.

How Do We Install a JAR into the Local Repository?

mvn install

How Do We Deploy a JAR to a Remote or Private Repository?

Use the Deploy Plugin.

First Approach

Configure the POM:

<project>
  <distributionManagement>
        <repository>
            <id>reposity id</id>
            <name>reposity name</name>
            <url>reposity url</url>
        </repository>
    </distributionManagement>
</project>

Configure the global Maven setting.xml file:

   <server>
      <id>internal.repo</id>
      <username>maven</username>
      <password>foobar</password>
    </server>

Then run:

mvn deploy

Second Approach

Use this approach to publish a JAR without a POM to the private repository so projects can reference it through their POMs.

mvn deploy:deploy-file -Durl=reposityUrl -DrepositoryId=repositoryId -Dfile=JAR_PATH -DgroupId=com.mycompany.ayy -DartifactId=child-one -Dversion=1.0.0 -Dpackaging=jar

How Do We Connect Maven to a Private Nexus Repository over HTTPS?

Reference article

  1. Configure SSL on Nexus.
  2. Download the private Nexus repository’s HTTPS certificate.
  3. Import it into the local JDK with keytool.
    keytool -importcert -file /home/nexus-cert.cert.der -alias nexus-cert -keystore ${JAVA_HOME}/lib/security/cacerts -storepass changeit -nopromp

Why? As discussed earlier, Maven runs on Java. It uses HttpClient to connect to the private repository, and HTTPS requires certificates. The JDK’s default certificate store does not contain our private repository’s certificate, so these steps are necessary.

The official documentation describes another approach, which I have not tested.

How Do We Check Code Style During a Maven Build?

Add the official Checkstyle Plugin. It checks code conventions during the build and fails the build if they are not met.

See the Checkstyle website for more information.

How Do We Build a Multi-Module Project?

Run the Maven commands in the top-level directory containing the parent pom.xml.

For example, package all modules:

mvn package

How Do We Speed Up Builds? What Does -T Mean in mvn -T 4 clean install?

See Maven Wiki > Proposals / Backlog > Complete > Parallel builds in Maven 3.

mvn -T 4 clean install # Builds with 4 threads mvn -T 1C clean install # 1 thread per cpu core mvn -T 1.5C clean install # 1.5 thread per cpu core

For more on mvn [options], run:

mvn -h

to display the options.

How Do We Replace web.xml Values Dynamically When Packaging a Traditional Web Application?

See this Stack Overflow answer. In practice, different scenarios may require different replacements in web.xml. Combine this with Maven profiles.

First Approach

<build>
<plugin>
<!--Replace web.xml values dynamically when packaging a WAR-->
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <webResources>
            <resource>
              <filtering>true</filtering>
              <directory>src/main/webapp</directory>
              <includes>
                <include>**/*</include>
              </includes>
            </resource>
          </webResources>
          <filters>
            <filter>src/main/resources/${build.profile.name}.properties</filter>
          </filters>
        </configuration>
      </plugin>
      </build>
<profiles>
    <profile>
      <id>ticket</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <build.profile.name>displayTicket</build.profile.name>
      </properties>
    </profile>
    <profile>
      <id>kk</id>
      <properties>
        <build.profile.name>displayKk</build.profile.name>
      </properties>
    </profile>
  </profiles>

The two properties files contain settings like the following. Here is displayTicket.properties:

display.name=ticket

The value to replace in web.xml is:

<web-app>
  <display-name>${display.name}</display-name>
</web-app>

Second Approach

Some examples use the Antrun Plugin to achieve the same result. Article

Useful Resources

The official documentation is the best resource. Read it often and look there for answers. If needed, search Google, which I find more dependable than Baidu.

  1. Getting started with Maven
  2. Maven frequently asked questions
  3. Spring Boot’s Maven packaging documentation

Example Project Used in This Article

Download; no CSDN credits required


Share this post:

Previous Post
Learning RabbitMQ and Spring AMQP (Part 4): JSON Message Bodies
Next Post
Creating a Custom Spring Boot Starter

Comments

Questions, corrections, and experiences are welcome. Sign in with GitHub to comment; both language versions share this discussion.

Comments are available on the live site only.