1. An overview of the

There are two ways to build a multi-module project using Maven:

  1. Aggregation, mainly to facilitate the rapid construction of projects;
  2. Base, mainly to eliminate duplication of configuration.

Their differences are as follows:

  1. For aggregation modules, it knows which modules are aggregated, but the aggregated modules do not know the existence of these aggregation modules;
  2. For the parent POM of an inheritance relationship, it does not know which submodules inherit from it, but those submodules must know what their POM is.

They are both packaged POM, and we often use a combination of the two.

Demo code: github.com/Quison/mave…

2. The polymerization

In some cases we build multiple projects at once, but with Maven’s aggregation features, we can build all at once. First, we need to build an additional Maven project for aggregation. It contains no files other than poM files, and it must be packaged as POM. The pom.xml file contains the following contents:

The < 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" > The < modelVersion > 4.0.0 < / modelVersion > < groupId > com. Konka < / groupId > < artifactId > MVN - aggergator < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < packaging > pom < / packaging > < modules > < module > MVN - module1 < / module > <module>mvn-module2</module> </modules> </project>Copy the code

In aggregation, a submodule can be parallel to a parent module, but the parent module needs to write the correct path to load the module.

3. The inheritance

When aggregating the various modules of the project through aggregation features, we found that there was a lot of duplication in the POM.xml configuration in the submodules, so we could eliminate that duplication by inheriting features.

As with object-oriented inheritance, inheritance in Maven is a parent-child structure, and we can declare configurations in the parent POM for the child POM to inherit. We need to create a Maven project called MvN-parent, which contains only POM files.

The < 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. Konka < / groupId > < artifactId > MVN - parent < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < packaging > pom < / packaging > < modules > < module > MVN - dao < / module > <module>mvn-service</module> <module>mvn-model</module> <module>mvn-web</module> </modules> </project>Copy the code

The pom.xml for the submodule is as follows:

The < project xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > com. Konka < / groupId > < artifactId > MVN - parent < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < / parent > < artifactId > MVN - dao < / artifactId > < packaging > jar < / packaging > <name>mvn-dao</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>com.konka</groupId> <artifactId>mvn-model</artifactId> <version>${project.version}</version> </dependency> </dependencies> </project>Copy the code

In a child module, its coordinates only need to be declared artifactId, and groupId and Version inherit coordinates from the parent module. And if the submodule depends on other modules, it needs to write its own dependency.

3.1 Inheritable elements

In Maven multi-module, the following elements can be inherited:

The element describe
groupId Project team ID, the core element of project coordinates
version Project version, the core element of project coordinates
description Description of the project
organazation Organizational information about the project
inceptionYear The founding year of the project
developers Developer information for the project
contributors Information about contributors to the project
distributionManagement Deployment information for the project
issueManagement Defect tracking system information for the project
ciManagement Continuous integration system information for the project
scm Version control system information for the project
mailingLists Mailing list information for the project
properties Custom Maven properties
dependencies Dependency configuration for the project
dependencyManagement Dependency management configuration for the project
repositories Warehouse configuration for the project
build Including project source directory configuration, output directory configuration, plug-in configuration, plug-in management configuration
reporting Includes report output directory configuration for the project, report plug-in configuration

3.2 Dependency Management

Once the elements listed in the previous section are configured in the parent module, the child module inherits. In some cases, however, a special child module such as util does not need to inherit the dependencies configured in the parent module such as SpringFramek. Use **dependencyManagement to resolve this situation.

Maven provides dependencyManagement elements that enable submodules to inherit the dependency configuration of their parent modules and ensure flexibility in the use of submodule dependencies.

First we use the dependencyManagement element in the MVN-parent file.

<? The XML version = "1.0" encoding = "utf-8"? > < 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. Konka < / groupId > < artifactId > MVN - parent < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < packaging > pom < / packaging > < modules > < module > MVN - dao < / module > <module>mvn-service</module> <module>mvn-model</module> <module>mvn-web</module> </modules> <properties> < springframework version > 2.5.6 < / springframework version > <. Junit version > 4.7 < / junit version > < / properties > <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-suport</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> </project>Copy the code

The content of the corresponding submodule pom. XML file is as follows:

<properties>
    <javax.mail.version>1.4.1</javax.mail.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    <dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    <dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    <dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-suppport</artifactId>
    <dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    <dependency>
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifacId>
        <version>${javax.mail.version}</version}
    <dependency>
</dependendies>
Copy the code

All springframework dependencies are configured with groupId and artifactId only, leaving out version. Junit also eliminates scope. This is because the child module inherits the dependencyManagement configuration from the parent module. Since the complete configuration has been declared in the parent POM, all child modules need to configure groupId and artifactId to obtain the complete dependency. However, if the child module does not declare the use of dependencies, declaring dependencyManagement in the parent module will not have any effect.

Under the dependencyManagement element, there is a bit import dependency scope, which is usually used with only one POM, Import the dependencyManagement configuration from the target POM into the dependencyManagement element of the current POM. For example, if you want to use the same dependencyManagement configuration as mVN-parent in another module, you can use the import scope in addition to the assignment, as shown below:

<dependencyManagement> <dependencies> <dependency> <groupId>com.konka</groupId> <artifactId>mvn-parent</artifactId> <version>0.0.1-SNAPSHOT</version> <type> POm </type> <scope>import</scope> <dependency> <dependencies> <dependencyManagement>Copy the code

3.3 Plug-in Management

Maven provides a dependencyManagement element to help manage dependencies. Similarly, Maven provides a pluginManagement element to help manage plug-ins. The dependencies configured in this element do not cause the actual plug-in invocation behavior. When the real Plugin element is configured in the POM and its groupId and artifactId match the plugins configured in the pluginManagement, It is the configuration of pluginManagement that affects the actual plug-in behavior.

For example, the parent POM is:

<build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.1.1</version> <executions> <id>attach-sources</id> <phase>verify</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins> </pluginManagement> </build>Copy the code

To use maven-source-plugin, you only need to configure the maven-source-plugin as follows.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
        </plugin>
    </plugins>
</build>
Copy the code

4. The reactor

4.1 Sequence of reactors

In more than one module of the Maven project, Reactor (Reactor) refers to a building structure composed of all the modules, for a single module project Reactor is the module itself, but for many modules, Reactor contains inheritance and dependencies between various modules, which can automatically calculate the reasonable module build order.

Maven reads the POM sequentially, builds the module if it has no dependencies, builds the dependent module first, and builds the dependent dependencies first if the dependency also depends on other modules.

Module dependencies form a directed acyclic graph of the reactor, and if cyclic dependencies occur, Mavne is prone to errors.

4.2 Cutting out the reactor

In general, users will choose to build an entire project or a single module, but sometimes they will want to build only complete modules. In other words, users need to tailor the reactor in real time. The order to cut the reactor was as follows:

  1. -am, –also-make Builds dependencies of listed modules at the same time;
  2. -AMD, –also-make-dependents builds modules that depend on all modules simultaneously;
  3. -pl, –projects Builds specified modules, separated by commas.
  4. -rf, -resume-from restores the reactor from the specified module.

In large projects, we can use these commands flexibly to build projects without having to build them all.

5. Merge dependencies between WAR packages

In some cases, to improve development efficiency and avoid reinventing the wheel, we can use the Maven-war-plugin in Maven to merge multiple Web projects. For example, we can develop a common UI and make it a common module for other projects to reuse. Maven’s Overlay mode allows you to deploy an external WAR package, including a static file and a class, to the current WAR package. The end result is to merge the two war packages, using webApp as the root directory by default, and store the files in the same path together. This path can be configured using the targetPath child element of overlay. In the demo, our MVN-Web module relies on the Common Web project. To merge common’s WAR package into mvn-web, just do the following configuration in the pom.xml file of the mvn-web main project: 1. Add dependencies:

< the dependency > < groupId > com. Konka < / groupId > < artifactId > webcommon < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > <type>war</type> </dependency>Copy the code

2. Configure plug-ins:

< plugin > < groupId > org. Apache. Maven. Plugins < / groupId > < artifactId > maven - war - the plugin < / artifactId > < version > 2.1.1 < / version > <configuration> <overlays> <overlay> <groupId>com.konka</groupId> <artifactId>webcommon</artifactId> </overlay> </overlays> </configuration> </plugin>Copy the code

This is simply merging the two WAR projects. We found that when we packaged and published the MVN-Web project, the resource files in WebCommon would appear in the MVN-Web package. We can access the index.jsp page in WebCommon by visiting mvn-web/pages/index.jsp. We can configure more overlays according to the needs of the project to meet the requirements of our project. Detailed overlay configuration, please see: maven.apache.org/plugins/mav…