源本科技 | 码上会

模块化之 Maven 模块化机制

2026/05/08
48
0

引言

在企业级项目与微服务架构开发中,传统单体 Maven 项目普遍存在代码耦合度高、依赖版本混乱、构建效率低下、多人团队协作困难等痛点。Maven 模块化开发 依托聚合、继承、依赖管理三大核心机制,将大型项目拆分为若干职责单一、可独立构建、可复用解耦的子模块。

模块化机制

聚合

顶级父工程通过 <modules> 标签统一管理所有子模块,在父工程目录执行 Maven 命令时,Maven 自动根据模块依赖拓扑顺序,依次完成所有子模块的清理、编译、测试、打包、安装,实现全局一键构建。

继承

所有子模块通过 <parent> 标签继承顶级父工程,统一复用项目编码、JDK 编译版本、基础坐标等通用配置,避免各模块重复编写冗余配置。

依赖管理

通过 dependencyManagement 结合 import 方式集中管控框架、中间件、第三方工具及自定义模块版本,仅声明版本不实际引入依赖;子模块引用依赖时无需指定版本,从根源杜绝版本冲突、版本不统一问题。

企业级模块化

工程目录

mall  顶级父工程(pom)
├── mall-dependencies         # 全局依赖版本统一管理(pom)
├── mall-common               # 公共工具通用模块(jar)
├── mall-system               # 核心大业务模块(整合用户/订单等业务)(jar)
└── mall-admin                # 项目唯一启动入口模块(jar)

包名规范

全局严格遵循层级命名

# 域名反转.项目名.模块名
com.lusifer.mall.common     # 公共工具模块
com.lusifer.mall.system     # 核心大业务模块
com.lusifer.mall.admin      # 统一启动模块

模块职责

  • mall

顶级父工程,pom 打包;负责聚合所有子模块、定义全局属性、通过 import 导入 Spring Boot 及自定义依赖管理,不编写任何业务代码

  • mall-dependencies

依赖管理模块,pom 打包;集中统一管理所有第三方框架、工具类、自定义业务模块版本,是项目唯一版本定义入口

  • mall-common

公共工具模块,jar 打包;仅存放通用工具类、常量类,不包含任何业务实体与业务逻辑,供所有业务模块依赖复用

  • mall-system

核心大业务模块,jar 打包;整合用户、订单等全量业务,内部独立划分 entity / mapper / service / controller 分层,无独立启动类

  • mall-admin

统一启动模块,jar 打包;项目唯一启动入口,整合所有业务模块依赖,负责 Spring Boot 容器启动、全局配置、组件扫描加载

搭建流程

顶级父工程

mall

<?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.lusifer</groupId>
    <artifactId>mall</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>mall</name>

    <!-- 聚合所有子模块 -->
    <modules>
        <module>mall-dependencies</module>
        <module>mall-common</module>
        <module>mall-system</module>
        <module>mall-admin</module>
    </modules>

    <!-- 全局统一属性 -->
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.boot.version>3.5.13</spring.boot.version>
    </properties>

    <!-- 依赖管理:使用 import 统一导入版本规范 -->
    <dependencyManagement>
        <dependencies>
            <!-- 导入 Spring Boot 官方版本管理 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 导入自定义项目依赖管理模块 -->
            <dependency>
                <groupId>com.lusifer</groupId>
                <artifactId>mall-dependencies</artifactId>
                <version>${project.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.11.0</version>
                    <configuration>
                        <source>17</source>
                        <target>17</target>
                        <parameters>true</parameters>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

依赖管理模块

mall-dependencies

<?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.lusifer</groupId>
    <artifactId>mall-dependencies</artifactId>
    <version>1.0.0</version>
    <name>mall-dependencies</name>
    <packaging>pom</packaging>

    <properties>
        <lombok.version>1.18.32</lombok.version>
    </properties>

    <!-- 统一声明所有依赖版本,子模块直接引用无需写版本 -->
    <dependencyManagement>
        <dependencies>
            <!-- 第三方工具依赖 -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>

            <!-- 自定义子模块版本声明 -->
            <dependency>
                <groupId>com.lusifer</groupId>
                <artifactId>mall-common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.lusifer</groupId>
                <artifactId>mall-system</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

公共工具模块

mall-common

仅提供通用工具类,无业务实体、无业务逻辑。

<?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">
    <parent>
        <groupId>com.lusifer</groupId>
        <artifactId>mall</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-common</artifactId>
    <name>mall-common</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

工具类代码

// 字符串工具类
package com.lusifer.mall.common.util;

public class StringUtils {
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }
}
// 日期工具类
package com.lusifer.mall.common.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateUtils {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static String getNowTime() {
        return LocalDateTime.now().format(FORMATTER);
    }
}

核心业务模块

mall-system

整合用户、订单全量业务,纯业务模块,无启动类,内部独立分层。

<?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">
    <parent>
        <groupId>com.lusifer</groupId>
        <artifactId>mall</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-system</artifactId>
    <name>mall-system</name>

    <dependencies>
        <dependency>
            <groupId>com.lusifer</groupId>
            <artifactId>mall-common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

用户业务代码

用户实体类

package com.lusifer.mall.system.entity;

import lombok.Data;
import java.io.Serializable;

@Data
public class User implements Serializable {
    private Long userId;
    private String username;
    private Integer age;
}

用户数据层

package com.lusifer.mall.system.mapper;

import com.lusifer.mall.system.entity.User;
import org.springframework.stereotype.Repository;

@Repository
public class UserMapper {
    public User selectById(Long userId) {
        User user = new User();
        user.setUserId(userId);
        user.setUsername("lusifer-mall-user");
        user.setAge(20);
        return user;
    }
}

用户业务层

package com.lusifer.mall.system.service;

import com.lusifer.mall.system.entity.User;
import com.lusifer.mall.system.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserMapper userMapper;

    public User getUserById(Long userId) {
        return userMapper.selectById(userId);
    }
}

用户控制层

package com.lusifer.mall.system.controller;

import com.lusifer.mall.system.entity.User;
import com.lusifer.mall.system.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @GetMapping("/{id}")
    public User getUserInfo(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

订单业务代码

订单实体类

package com.lusifer.mall.system.entity;

import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
public class Order {
    private Long orderId;
    private Long userId;
    private BigDecimal orderPrice;
    private LocalDateTime createTime;
}

订单数据层

package com.lusifer.mall.system.mapper;

import com.lusifer.mall.system.entity.Order;
import org.springframework.stereotype.Repository;

@Repository
public class OrderMapper {
    public void insertOrder(Order order) {
        System.out.println("订单入库完成:" + order);
    }
}

订单业务层

package com.lusifer.mall.system.service;

import com.lusifer.mall.system.entity.Order;
import com.lusifer.mall.system.entity.User;
import com.lusifer.mall.system.mapper.OrderMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
public class OrderService {
    private final UserService userService;
    private final OrderMapper orderMapper;

    public Order createOrder(Long orderId, Long userId) {
        // 调用模块内用户服务
        User user = userService.getUserById(userId);
        Order order = new Order();
        order.setOrderId(orderId);
        order.setUserId(userId);
        order.setOrderPrice(new BigDecimal("199.00"));
        order.setCreateTime(LocalDateTime.now());
        orderMapper.insertOrder(order);
        return order;
    }
}

订单控制层

package com.lusifer.mall.system.controller;

import com.lusifer.mall.system.entity.Order;
import com.lusifer.mall.system.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order")
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;

    @PostMapping("/create")
    public Order createOrder(@RequestParam Long orderId, @RequestParam Long userId) {
        return orderService.createOrder(orderId, userId);
    }
}

统一启动模块

mall-admin

项目唯一启动入口,整合核心业务模块

<?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">
    <parent>
        <groupId>com.lusifer</groupId>
        <artifactId>mall</artifactId>
        <version>1.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-admin</artifactId>
    <name>mall-admin</name>

    <dependencies>
        <!-- 依赖核心业务模块 -->
        <dependency>
            <groupId>com.lusifer</groupId>
            <artifactId>mall-common</artifactId>
        </dependency>
        <dependency>
            <groupId>com.lusifer</groupId>
            <artifactId>mall-system</artifactId>
        </dependency>
        <!-- Spring Boot 核心依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

启动类

package com.lusifer.mall.admin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.lusifer.mall")
public class MallAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(MallAdminApplication.class, args);
    }
}

配置文件

server:
  port: 8080
spring:
  application:
    name: mall-admin

项目构建

构建命令

在顶级父工程 mall 根目录执行:

mvn clean install

项目运行测试

  1. 仅启动 mall-admin 模块下 MallAdminApplication

  2. 访问用户接口 (GET):http://localhost:8080/user/1

  3. 访问订单接口 (POST):http://localhost:8080/order/create?orderId=1001&userId=1

  4. 业务模块内的跨业务调用、Spring 容器扫描加载均正常。

模块化开发规范

  1. 顶级父工程、依赖管理模块统一使用 pom 打包,仅做配置与聚合,禁止编写业务代码;

  2. 严格遵循 域名反转. 项目名. 模块名 包名规范,统一项目层级结构;

  3. mall-common 只存放通用工具类、常量类,禁止存放业务实体与业务逻辑;

  4. mall-system 大业务模块仅作为依赖 Jar 包,禁止自定义启动类,统一由 mall-admin 启动;

  5. 所有版本统一在 mall-dependencies 中管控,业务模块引入依赖不允许指定版本号

  6. 模块间遵循单向依赖,禁止循环依赖,依赖顺序:common → system → admin

  7. 必须在 mall 根目录执行构建,保证 Maven 按拓扑顺序编译、打包、安装。

面向对象设计原则

  • 单一职责:每个模块职责完全隔离:父工程负责聚合、dependencies 负责版本管理、common 负责通用工具、system 负责全量核心业务、admin 负责容器启动;业务内部按领域、分层各司其职

  • 开闭原则:新增业务功能时,无需修改现有工程配置与代码,仅在 mall-system 内扩展对应代码即可,对扩展开放、对原有代码修改关闭

  • 依赖倒置:业务模块不依赖具体框架版本与底层实现,而是依赖统一版本管理规范与通用公共能力,底层版本升级不影响上层业务代码

  • 迪米特法则:模块之间仅通过 Maven 依赖弱关联,内部实现细节对外隐藏;业务模块只依赖必需的公共模块,不感知无关模块内部结构

  • 组合聚合:通过 Maven 模块依赖组合、Spring 构造器注入组合复用现有能力,而非通过类继承实现复用,有效降低耦合度