Super detailed analysis of the pom.xml file in Maven

We use maven more or less to manage and build our projects in our usual development. Even if we use various framework jar packages, they are introduced through Maven, so I think it is necessary to understand each of the pom.xml files. A configuration to help me better use Maven, an automation tool;

1. Download and install Maven

First of all, we need to build a Maven environment. Since this article focuses on sharing and analyzing the elements in pom.xml, we will not elaborate too much on the download and installation of Maven. You can refer to the installation configuration of Maven and build the Maven environment in IDEA to operate by yourself. If you have any questions, you can leave a message in the comment area;

2. What is pom?

POM whole process Project Object Model, also known as Project Object Model. He is the basic unit of work of the Maven project. It is an XML (Extensible Markup Language) file that contains the basic information of the project and is used to describe how the project is built, declare project dependencies, and so on. When executing a task or goal, Maven will look for the POM in the current directory and read it to obtain the required configuration information to execute the goal, which belongs to the project-level configuration file.

In short, the most powerful thing about pom is to provide one-stop support, which can be used to manage: source code, configuration files, defect tracking system (defect tracking system), organization and licenses (licenses), URL address where the project is located, developer information and Roles, project dependencies, and all other aspects related to the code lifecycle. In Maven, only one pom.xml file is needed. It can be said that pom.xml is the core of Maven!

A complete pom.xml file is placed under the root directory of the project;

3. More complete pom elements

The overall structure of pom, more detailed pom can be seen Super POM_POM file overall configuration description.pdf;

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <!-- The Basics basic part -->
  <groupId>...</groupId>
  <artifactId>...</artifactId>
  <version>...</version>
  <packaging>...</packaging>
  <dependencies>...</dependencies>
  <parent>...</parent>
  <dependencyManagement>...</dependencyManagement>
  <modules>...</modules>
  <properties>...</properties>
 
  <!-- Build Settings build settings -->
  <build>...</build>
  <reporting>...</reporting>
 
  <!-- More Project Information More Project Information -->
  <name>...</name>
  <description>...</description>
  <url>...</url>
  <inceptionYear>...</inceptionYear>
  <licenses>...</licenses>
  <organization>...</organization>
  <developers>...</developers>
  <contributors>...</contributors>
 
  <!-- Environment Settings environment settings -->
  <issueManagement>...</issueManagement>
  <ciManagement>...</ciManagement>
  <mailingLists>...</mailingLists>
  <scm>...</scm>
  <prerequisites>...</prerequisites>
  <repositories>...</repositories>
  <pluginRepositories>...</pluginRepositories>
  <distributionManagement>...</distributionManagement>
  <profiles>...</profiles>
</project>

4. Generate the pom content of the Maven project by default

Among them, groupId, artifactId, and version form the unique coordinates of the project.

<?xml version="1.0" encoding="UTF-8"?>
<!--project is the root element of pom.xml, which contains some constraint information of pom.xml, declares some POM-related namespaces and xsd elements -->
<!-- xmlns namespace, similar to package name -->
<!-- xmlns:xsi xml follows the label specification -->
<!--xsi:schemaLocation defines the address of xmlschema, the grammar that needs to be followed when writing xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- specifies the current pom.xml version, which is currently fixed at version 4.0.0. -->
    <modelVersion>4.0.0</modelVersion>
    <!-- coordinates -->
    <!-- which group it belongs to, generally the reverse order of the organization or company domain name where the project is located -->
    <groupId>com.sx.kak</groupId>
    <!-- Define the unique ID of the current project in the group. There may be multiple projects under a groupId, which are distinguished by artifactId -->
    <artifactId>nacospro</artifactId>
    <!-- Define the current version of the project -->
    <version>1.0-SNAPSHOT</version>
    <!-- Packaging type, possible values: pom , jar , maven-plugin , ejb , war , ear , rar , par, etc. -->
    <packaging>jar</packaging>
    <!-- The name of the project (can be omitted) The default artifactId, which can be modified to a user-friendly name -->
    <name>nacospro</name>
    <!-- The address of the warehouse (can be omitted) -->
    <url>http://maven.apache.org</url>

    <!--The defined dependency list, all dependent packages need to be written in this tag -->
    <dependencies>
        <!--Specific dependencies -->
        <dependency>
            
        </dependency>
    </dependencies>
</project>

5. Custom attribute variables

We can customize Maven properties under the POM element. The defined attribute variables are used elsewhere.

<!-- Defined attribute variables, used elsewhere -->
<properties>
    <!-- Java version -->
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- Use ${hutool.version} -->
    <hutool.version>5.0.6</hutool.version>
    <!-- Use via ${pagehelper.version} -->
    <pagehelper.version>1.3.0</pagehelper.version>
</properties>

6. Dependency management

Dependencies: Describes all dependencies related to the project, which constitutes a link in the project construction process; they will be automatically downloaded from the warehouse defined by the project, and a project can have more dependencies;

You can find dependencies through https://mvnrepository.com/ and obtain corresponding coordinates; for specific operations, please read Maven’s installation and configuration, and build a Maven environment in IDEA;

6.1, overall dependency list

<!--Defined dependency list, all dependent packages need to be written in this tag-->
<dependencies>
    <!--HuTool Toolkit -->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>${hutool.version}</version>
    </dependency>

    <!--pagehelper-->
    <dependency>
        <!--The organization name of the dependency-->
        <groupId>com.github.pagehelper</groupId>
        <!--Dependency subproject name-->
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <!--Dependency version-->
        <version>${pagehelper.version}</version>
        <!-- Scope of application of dependencies -->
        <scope>test</scope>
        <!-- Optional dependency, which hides the resources currently relied on from the outside, is opaque; if others rely on this project, the configured one will not depend on other people's projects -->
        <optional>true</optional>
        <!-- Exclude dependencies, actively disconnect dependent resources, use when excluding dependency conflicts in the project, do not depend on the project, and the excluded resources do not need to specify the version -->
        <exclusions>
            <exclusion>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

6.2, Transitivity of dependencies

Direct dependencies: dependencies established through dependency configuration in the current project;

Indirect dependency: The current project pom is configured to depend on A, and A depends on B, so this project also depends on B, and B is the indirect dependency of this project.

As shown in the figure below: A depends on B, and B depends on C. At this time, B is a direct dependency of A, and C is an indirect dependency of A.

We all know that dependencies in Maven are transitive. No matter how many indirect dependencies exist in the Maven project, only the direct dependencies need to be defined in the POM, and there is no need to define any indirect dependencies. Maven will automatically read the direct dependencies of the current project. The POM, which introduces the necessary indirect dependencies into the current project in the form of transitive dependencies, can help users simplify the configuration of the POM.

The dependencies among A, B, and C in the above figure, according to Maven’s dependency transfer mechanism, we only need to define its direct dependency on B in the POM of project A, and define its direct dependency on C in the POM of project B, and Maven will resolve A’s direct dependency on B’s POM introduces indirect dependency C into project A in the form of transitive dependency.

6.3, problems that may be caused by dependency transmission

Through the dependency transfer relationship, the dependency tree can be rapidly grown to a large magnitude, but it is very likely that there will be repeated dependencies, dependency conflicts, etc. Maven provides the following functions to deal with these situations:

  • Dependency scope
  • Dependency mediation
  • Optional dependencies
  • Excluded dependencies
  • Dependency management

6.3.1, scope dependent scope

We can use the scope element in the dependency declaration of the POM to control the relationship between the dependency and the three classpaths (compile classpath, test classpath, and run classpath). This is the dependency scope.

There are 6 commonly used optional scopes for scope dependencies:

1) compile: the default value, indicates the scope of compilation dependencies; applicable to all stages (compile, test, run), and will be released together with the project. Indicates that the jar package has always existed/required;

2) Provided: Indicates that the scope of dependencies has been provided; required for compiling and testing, not required for runtime, and will not be packaged. Such as servlet.jar;

3) runtime: indicates that the scope of dependencies is provided at runtime; only used at runtime, such as JDBC driver, applicable to the running and testing stage;

4) test: Indicates the scope of test dependencies; When testing is valid and used to compile and run the test code. will not be released with the project;

5) system: similar to provided, needs to explicitly provide the jar containing dependencies, Maven will not look for it in the Repository (not recommended);

6) optional: When the project itself is depended on, mark whether the dependency is passed. Used for continuous dependencies;

The relationship between dependency scope and three classpaths:

6.3.2, dependent regulation

Users in Maven only need to care about the direct dependencies of the project, and do not need to care about which indirect dependencies these direct dependencies will introduce. But when there are multiple introduction paths for an indirect dependency, in order to avoid the problem of repeated dependencies, the introduction path of the indirect dependency will be determined through dependency adjustment.

6.3.2.1, path priority

When the same resource appears in the dependency, the deeper the level, the lower the priority, and the shallower the level, the higher the priority;

A has the following dependencies
Case 1: A->B->C->D
Case 2: A->E->D

D is an indirect dependency of A, but there are two different versions in the two imported cases, which cannot be imported at the same time, otherwise it will cause the problem of repeated dependencies. According to the first principle of Maven dependency adjustment: the shortest path is preferred, the path length of case 1 is 3, and the path length of case 2 is 2, so the indirect dependency D will be introduced into A from the path A->E->D .

6.3.2.2, statement priority

When resources are depended on at the same level, the earlier configurations override the later ones;

A has the following dependencies
Case 1: A->B->D
Case 2: A->C->D

<dependencies>
    ...
    <dependency>
        ...
        <artifactId>B</artifactId>
        ...
    </dependency>
    ...
    <dependency>
        ...
        <artifactId>C</artifactId>
        ...
    </dependency>
    ...
</dependencies>

D is an indirect dependency of A, and the lengths of the two imported paths are both 2. At this time, the priority of the path cannot be resolved, and the first declaration needs to be used first; it can be seen from the above configuration that because the dependency declaration of B is earlier than that of C, So the indirect dependency of case 1 will be introduced into A from A->B->D path.

Priority is to use the first principle to solve the problem, if the first principle cannot be solved, then use the second principle to solve it;

6.3.2.3, special priority

When a resource is configured with different versions of the same resource, the later configuration overrides the first configuration (not an example);

6.3.3, optional dependencies (detailed in 6.4.2)

Configure optional as true/false in the dependency to pass it down. If it is configured as true, others depend on this project, and the configured ones will not depend on other people’s projects. If it is false, it can be passed down, which is called indirect dependency;

6.3.4, exclude dependencies (detailed in 6.4.1)

Coordinates contained in exclusions, exclude dependencies contained in dependent packages, no need to add version, direct category exclusion, exclude dependencies can set whether to use indirect dependencies in current dependencies. Pay attention to distinguishing from optional dependencies, which can achieve the same effect.

6.4, exclude dependencies and optional dependencies

Maven dependencies are transitive. Without considering factors such as the scope of dependencies, Maven will introduce indirect dependencies C into A according to the dependency transfer mechanism. But if A wants to exclude indirect dependencies C, Maven provides two solutions: exclusion dependencies and optional dependencies.

6.4.1, exclude dependencies

Excluding dependencies is to control whether the current project uses indirect dependencies passed down from its direct dependencies;

  • The exclusions element can contain several exclusion sub-elements to exclude several indirect dependencies;

  • The exclusion element is used to set specific excluded indirect dependencies. This element contains two sub-elements: groupId and artifactId, which are used to determine the coordinate information of the indirect dependencies that need to be excluded;

  • You only need to set groupId and artifactId in the exclusion element to determine the dependencies that need to be excluded, without specifying the version version.

6.4.2, optional dependencies

Optional dependencies are used to control whether the current dependency is passed down to become an indirect dependency;

  • The default value of optional is false, which means that it can be passed down and called indirect dependency;
  • If the value of the optional element is true, it means that the current dependency cannot be passed down to become an indirect dependency.

6.4.3 Examples of excluded dependencies and optional dependencies

Suppose A depends on B, B depends on X, and B depends on Y. B implements two features, one of which depends on X, and the other depends on Y, and the two features are mutually exclusive. Users cannot use the two features at the same time, so A needs to exclude X. At this time, you can In A, the indirect dependence on X is excluded.

6.4.3.1 Example of excluding dependencies

Excluding dependencies is implemented by using the exclusions element in A, which can contain several exclusion sub-elements to exclude several indirect dependencies. The sample code is as follows.

<project
         xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sx.kak</groupId>
    <artifactId>A</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.sx.kak</groupId>
            <artifactId>B</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <!-- set exclusions -->
                <!-- The exclusion of dependencies must be based on the indirect dependencies in the direct dependencies set to be dependent on false -->
                <!-- Set whether to use indirect dependencies in the current dependencies -->
                <exclusion>
                    <!--Set specific exclusions-->
                    <groupId>com.sx.kak</groupId>
                    <artifactId>X</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

6.4.3.2. Example of selecting dependencies

Use the optional element in the dependency declaration of B’s POM on X to set it as an optional dependency. The example configuration is as follows.

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sx.kak</groupId>
    <artifactId>B</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>net.biancheng.www</groupId>
            <artifactId>X</artifactId>
            <version>1.0-SNAPSHOT</version>
            <!--Set optional dependencies, true means that the current dependencies cannot be passed down to become indirect dependencies -->
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

6.4.3, exclude dependencies VS optional dependencies

Excluding dependencies and optional dependencies can both exclude indirect dependencies in the project, but the implementation mechanisms of the two are completely different.

  1. Excluding dependencies is to control whether the current project uses the indirect dependencies passed down from its direct dependencies;
  2. Optional dependency is to control whether the dependency of the current project is passed down;
  3. Optional dependencies have higher priority than excluded dependencies;
  4. If both exclusion and optional dependencies are used for the same indirect dependency, the value of the optional dependency must be false, otherwise the exclusion dependency will not take effect.

7. Build plugin configuration

Build is understood as the information needed to build the project, which is mainly used for compilation settings;

7.1, two part configuration of Build

In Maven’s pom.xml file, Build-related configuration includes two parts, one is build and the other is reporting.

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <!-- called Project Build, which is a direct child element of <project> -->
  <build>...</build>
 
  <profiles>
    <profile>
      <!-- called Profile Build, which is a direct child element of <profile> -->
      <build>...</build>
    </profile>
  </profiles>
</project>

Profile Build contains basic build elements, and Project Build also contains two special elements, namely various Directory and extensions.

7.2, commonly used Build structure

<!-- information needed to build the project -->
<build>
    <!-- list of plugins used -->
    <plugins>
        <!-- The plugin element contains the information needed to describe the plugin -->
        <plugin>
            <!-- The group ID of the plugin in the repository -->
            <groupId>org.springframework.boot</groupId>
            <!-- The artifact ID of the plugin in the repository -->
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
    <!-- This element describes a list of all resource paths related to the project, such as property files related to the project, and these resources are included in the final package file. -->
    <resources>
        <!-- This element describes all resource paths related to the project or test -->
        <resource>
            <!-- Describe the directory where resources are stored, the path is relative to the POM path -->
            <directory>src/main/java</directory>
            <!-- list of included patterns, e.g. **/*.xml. -->
            <includes>
                <include>**/*.xml</include>
            </includes>
            <!-- Whether to use the parameter value instead of the parameter name. The parameter value is taken from the properties configured in the properties element or file, and the file is listed in the filters element -->
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

8. Write at the end_Super POM

Seeing this, do you feel that the understanding of pom has reached a new level? I often use POM files but I don’t know much about it. Sometimes I use it like that but I don’t know what the label means; so I have to understand each label. Although the idea of the role of Maven may still be lacking, it did give me a better understanding of Maven; I think there are still many things that have not been sorted out, and I will continue to study and sort them out later!

Super POM is a relatively complete POM file. If you encounter something you don’t understand, you can search in the document; if you have a friend who wants a super POM, you can see the general configuration description of the super POM_POM file.pdf, or leave an email address in the comment area privately sent to you;

Reference article

  • https://maven.apache.org/pom.html#What_is_the_POM
  • https://blog.csdn.net/jk418756/article/details/87917776
  • https://www.cnblogs.com/cy0628/p/15034450.html

Reposted from: Super-detailed analysis of the pom.xml file in Maven – Willing Kaka’s Blog – CSDN Blog

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge Java skill tree Java overviewMaven basics 118347 people are studying systematically