Partition and dependency inheritance of multiple maven modules in spring boot project

Necessity of multi module division

Usually, a complex large-scale project will be divided into multiple modules. In structured programming, the principle of module division is high cohesion within modules and low coupling between modules

Splitting a complex project into multiple modules is conducive to collaborative development and module reuse

Start the multi module springboot project for the first time

1. Initialize the tool to create a new springboot project: project root

Here, the outer project (project root) is called the parent module, and the pom.xml under the direct path of project root is called the top-level POM file

Then modify pom.xml to delete other unused resource folders so that they can be inherited by all sub modules

<?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>
    <!--Reference the default parent project, so you don't have to declare the version number-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!--Each sub module is added to project-root In the project-->
    <modules>
        <module>project-child</module>
        <module>project-server</module>
    </modules>

    <!--The top-level dependency is referenced as the whole project-->
    <!--Organization name-->
    <groupId>org.example</groupId>
    <!--Module name, unique identification-->
    <artifactId>project-root</artifactId>
    <!--Project version-->
    <version>1.0-SNAPSHOT</version>


    <name>project-root</name>
    <description>top floor pom rely on</description>
    <!--Parent project packaging method must be pom form-->
    <packaging>pom</packaging>
    <properties>
        <!--Parent module properties Attributes can be inherited and used by sub modules and can be used for unified version management-->
        <junit.version>4.13</junit.version>
        <lombok.version>1.18.12</lombok.version>
    </properties>
<!--
dependencyManagement Label function:
    1.Used at the top of the project pom In the file, the dependency and version of the project are managed uniformly
    2.This label cannot be used in the of subprojects pom In the file, because the dependency in the tag is only a declaration dependency, it does not implement the introduction
    3.The dependencies in this tag will not be actively introduced into the subproject. If the subproject wants to reference the dependencies in this tag, it needs to be explicitly declared, but the version can not be specified,
      because version and scope All read from the top level pom
    4.If you want to customize the version of a subproject, you only need to dependencies Just state it in

dependencies Use of labels:
   If not used in parent project dependencyManagement Label, direct use dependencies label,
   So all in dependencies Dependencies in are automatically introduced and inherited by all subprojects by default
-->
    <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
<!--top floor pom Already referenced in dependency spring-boot-starter-parent,So don't repeat it here-->
<!--       <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-web</artifactId>-->
<!--        </dependency>-->
    </dependencies>
    </dependencyManagement>
        <build>
        <!--Unified plug-in management. These plug-ins can be used after they are declared in sub modules-->     
        <pluginManagement>
            <!--spring Generate executable jar Package plug-ins, be careful not to use them at the same time org.apache.maven.plugins use-->
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

2. Create a new mouse: Project child on the project root project name

This sub module inherits the parent module project root

There can be multiple sub modules, all of which are inherited from the parent module

The coupling degree between sub modules should be as low as possible to reduce the cross dependence between sub modules as much as possible

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--Each sub module refers to a unique parent module, so that you do not need to specify a version number when importing a parent module dependency-->
    <parent>
        <groupId>org.example</groupId>
        <artifactId>project-root</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <!-- Basic information of current module-->
    <groupId>com.example</groupId>
    <artifactId>project-child</artifactId>
    <!--With the parent module, the child module does not need to specify the version number-->
    <!--<version>0.0.1-SNAPSHOT</version>-->
    <description>Demo project for Spring Boot</description>

    <!-- Module packaging method-->
    <packaging>jar</packaging>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
<!--If a sub module is introduced into another module as a dependency, the other module will introduce all dependencies used by the sub module
    If another module imports other dependencies used by the sub module again, it will only be imported once without error
-->
<!--       <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-web</artifactId>-->
<!--        </dependency>-->
    </dependencies>
</project>

3. Create a new moudle: project server on the project root project name

  • Specifies the master module, which also inherits the parent module: project root
  • The springboot initiator is set in this module, and all other sub modules can be called
  • When you need to call a sub module, you can directly import it in the form of dependency tag
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--Reference parent module-->
    <parent>
        <!--Organization name-->
        <groupId>org.example</groupId>
        <!--Module name, unique identification-->
        <artifactId>project-root</artifactId>
        <!--Project version-->
        <version>1.0-SNAPSHOT</version>
    </parent>


    <!--Main module information-->
    <groupId>com.example</groupId>
    <artifactId>project-server</artifactId>
    <!--The child module uses the same version as the parent module by default-->
    <!--<version>0.0.1-SNAPSHOT</version>-->
    <packaging>jar</packaging>
    <name>project-server</name>

    <description>Main module for starting springboot application</description>
	
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--Reference to other sub modules-->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>project-child</artifactId>
            <!--Because the version of the whole project is unified and the version of each sub module is consistent with that of the parent project, the version number of the parent project is directly used-->
            <version>${project.version}</version>
        </dependency>
        <!--Reference parent module-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        <dependency>-->
        <!--            <groupId>org.springframework.boot</groupId>-->
        <!--            <artifactId>spring-boot-starter-test</artifactId>-->
        <!--            <scope>test</scope>-->
        <!--            <exclusions>-->
        <!--                <exclusion>-->
        <!--                    <groupId>org.junit.vintage</groupId>-->
        <!--                    <artifactId>junit-vintage-engine</artifactId>-->
        <!--                </exclusion>-->
        <!--            </exclusions>-->
        <!--        </dependency>-->
    </dependencies>
    <!--
    Multi module construction method:
    1.Main module: the module where the startup class is located. This class is used to call other sub modules. Such a main module must be specified in multiple modules
    2.One or more sub modules. The main module must call the sub module through dependency Label to introduce
    3.You only need to add packaged plug-ins in the main module, not in other modules
    4.use mvn package When packaging, select the main module, and all dependent sub modules will be packaged
    -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4. Module test

1. Project child module test class

package com.example.projectchild.entity;

import lombok.Getter;
import lombok.Setter;

/**
 * @Author: wonzeng
 * @CreateTime: 2020-10-08
 */
@Setter
@Getter
public class User {
    private Integer id;
    private String name;
    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
}

2. Project server module test class

The project child module is introduced in the pom.xml of this module in the form of dependency, so that the User test class can be used

package com.example.projectserver.controller;

import com.example.projectchild.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;

/**
 * @Author: wonzeng
 * @CreateTime: 2020-10-08
 */
@RestController
public class HelloController {
    public HelloController() {
    }
    /**
     * Exception occurred:
     *  org.springframework.http.converter.HttpMessageNotWritableException
     *  Because the User entity does not provide setter and getter methods, it cannot be converted to json
     */
    @GetMapping(value={"/hello","/"})
    public User hello(){
        System.out.println("Hello World!");
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("Current time:"+localDateTime.toLocalTime().toString());
        User user = new User(101,"Zhang San");
        return user;
    }
}

3. Project server module launcher

Post startup access: http://localhost:8080/ It indicates that the module integration is successful

package com.example.projectserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ChildServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ChildServerApplication.class, args);
    }

}

In addition to directly running the main method, you can also run the command under the root directory of the springboot application:

mvn spring-boot:run

4. Packaging and startup

Execute the following command:

mvn clear
mvn package

Switch to the package output directory and execute the command for the project xxx.jar:

java -jar xxx.jar

Keywords: Spring Boot

Added by katlis on Thu, 30 Sep 2021 22:52:17 +0300