多Module项目的设计

Module的概念

熟悉Java开发的对于Maven的模块应该并不陌生,它使用一个名为 POM(Project Object Model)的 XML 文件来描述项目结构和配置信息。一般创建单体项目,都是直接创建一个Maven的project,最终是一个Module,如下图:

同时一个项目可以包含多个模块(module),每个模块都是一个独立的 Maven 项目,拥有自己的 POM 文件,最终是以集成Module的形式呈现,如下:

Maven 多Module的基本结构

cola-demo-project/
├── pom.xml
└── cola-module/
    ├── module-a/
    │   ├── pom.xml
    │   └── src/
    ├── module-b/
    │   ├── pom.xml
    │   └── src/
    └── module-c/
        ├── pom.xml
        └── src/

采用集成多个Module的项目代码结构主要体现在Pom配置文件中

父项目的职责

父项目仅有一个pom文件,无任何源代码。父项目的主要职责集中在pom配置文件中。主要的作用有:

  • 依赖管理:定义所有子模块共享的依赖,避免在每个子模块中重复相同的依赖配置。
  • 模块管理:通过 modules 元素列出所有子模块的目录名称,Maven 会自动寻找这些目录下的 pom.xml 文件。
  • 插件管理:定义共享的插件配置,子模块可以继承或覆盖这些配置。
  • 构建配置:设置项目的构建配置,如源代码和编译版本的设置。

依赖管理

pom.xml 使用 <dependencyManagement> 标签来管理所有子模块的依赖版本,确保项目中依赖的一致性。子模块可以在自己的 pom.xml 中声明依赖,而不需要指定版本,Maven 会从父 pom.xml 中获取相应的版本。

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.ci</groupId>
      <artifactId>child2</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>
</dependencyManagement>

如果子模块需要使用child2这个依赖,因为父项目中已经定义了该依赖,则子模块只需在 <dependencies> 中声明依赖的坐标(即 groupIdartifactId),而不需要指定版本号。Maven 会自动使用父项目中定义的版本。 

如果子模块需要使用一个与父项目不同的版本,则子模块必须在 <dependencies> 中明确指定所需的版本号。这将覆盖父项目中定义的版本。

<dependencyManagement> 的作用是提供一个集中管理依赖版本的地方,从而避免在每个子模块中重复相同的版本声明,并确保项目中依赖的一致性。子模块可以继承并使用这些管理的依赖,除非有特殊需要使用不同版本。

模块管理 

在多模块项目中,项目的描述、组织信息、开发者信息等这些内容统一管理在父项目中,父项目的 pom.xml 配置了 packagingpom,这表明父项目本身不会产生一个可部署的构件,而是用来聚合子模块的构建配置。

<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.mycompany.myapp</groupId>
    <artifactId>my-app-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <!-- 子模块列表 -->
    <modules>
        <module>my-app-util</module>
        <module>my-app-dao</module>
        <module>my-app-service</module>
        <module>my-app-web</module>
    </modules>
    
    <!-- 依赖管理,子模块可以继承这些依赖版本 -->
    <dependencyManagement>
      ……
    </dependencyManagement>

   <!-- 插件管理,子模块可以继承或引用这些插件配置 -->
    <pluginManagement>
      ……
    </pluginManagement>

   <!-- 构建配置,可以包含共用的构建逻辑或扩展插件配置 -->
    <build>……</build>
</project>

插件管理

父项目的 pom.xml 可以使用 <pluginManagement> 来统一配置插件。

<pluginManagement>
  <plugins>
    <!-- Maven 编译插件 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
    <!-- 其他插件 -->
  </plugins>
</pluginManagement>

构建管理

在父项目的 pom.xml 中,通过 <build> 标签定义了通用的构建配置。

<build>
  <pluginManagement> <!-- 插件管理配置 -->
    <!-- 插件配置 -->
  </pluginManagement>
  <plugins> <!-- 插件配置 -->
    <!-- 可以在这里添加一些所有子模块共用的插件 -->
  </plugins>
  <finalName>${project.artifactId}-${project.version}</finalName>
</build>

多Module的项目组织

其实不单是多Module,单Module的项目也存在项目规划的问题,所谓项目规划是指,对于module的拆分,对于单Module则是包一级别的划分,对于多Module则是module或者说组件一级的的划分,不论是单Module还是多module主要的划分原则主要有两个:

  • 基于技术维度的划分
  • 基于业务维度的划分

基于技术维度的项目结构

所谓技术维度的划分是指架构视角的划分,例如MVC架构,我的一个多Module项目的子项目是按技术分层来划分的,则会产生Controller、Service、Dao、Util四个Module:

    <!-- 父项目基本信息 -->
    <groupId>com.mycompany.myapp</groupId>
    <artifactId>my-app-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <!-- 子模块列表 -->
    <modules>
        <module>my-app-util</module>
        <module>my-app-dao</module>
        <module>my-app-service</module>
        <module>my-app-controller</module>
    </modules>

此种划分的优势在于,在项目开发中偏向于技术流,能最大程度的保证架构设计的实现,技术可以统一管理开发,极大的降低技术开发成本,模块间的依赖可以在一开始就确定,并且借助maven的依赖限定死,即基于技术理论和架构设计,就规定好各个子模块间的依赖关系。

缺点是对于业务不够友好,不利于业务架构的灵活扩展,随着业务的膨胀,每一个module的代码会爆炸式的增长。因此更适用于业务相对简单、体量相对较小的项目。

基于此种划分,比较成熟的方案是,横向上是以module为单位的技术流划分,统一且明确技术架构边界,纵向上以命名规范、统一为基础,以包的形式来完成业务层面的划分。

基于业务维度的项目结构

基于业务维度的划分则更偏向于业务,每个module面向的不同的业务领域,整个项目就是集成各个领域间的业务关系。

  <!-- 父项目基本信息 -->
    <groupId>com.mycompany.myapp</groupId>
    <artifactId>my-app-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <!-- 子模块列表 -->
    <modules>
        <module>my-app-order</module>
        <module>my-app-account</module>
        <module>my-app-pay</module>
        <module>my-app-product</module>
    </modules>

 

每个module都是“麻雀虽小、五脏俱全”,每个module都是完整的架构体系,以web项目为例,每个module内部都包含各自的Controller、Service、Dao,技术则内缩到单module内包级别来体现。module视角上则是复杂业务的关系维护。

基于业务维度的项目结构,每个module独立管理开发,面向专业业务,聚焦于业务内容的开发,保证了业务的独立性和扩展性,随着业务的扩展,可以直接新增module,每个module具备完整的技术流,独立演进开发。

缺点就是业务的划分会渗透到技术,依赖关系会变得十分复杂,使用此种方式,需要有较为完善的业务模型,明确的业务体系;适合业务场景复杂,体量较大的项目。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值