Maven管理多模块应用

1、为什么要进行多模块的拆解

Maven多模块项目通过合理的模块拆分,实现代码的复用,便于维护和管理。尤其是一些开源框架,也是采用多模块的方式,提供插件集成,用户可以根据需要配置指定的模块。微服务项目是以多模块的方式开发,分包部署;

Maven多模块项目适用于大型的、复杂的,需要分层设计和模块化开发的项目。以下是适合采用Maven多模块项目的一些场景:

  • Web应用程序或服务端应用程序,特别是对于由多个子系统或模块组成的复杂应用程序。

  • 基于微服务架构进行开发,其中每个服务都是一个独立的模块。

  • 企业级应用程序,需要包含多个不同的子系统或模块,并且这些模块需要共享相同的依赖项和配置信息。

  • 应用商店或插件式系统,其中每个应用程序或插件都可以作为一个单独的模块。

总之,如果要开发大型、复杂的应用程序,使用Maven多模块项目可以提高代码的可读性、可维护性和可扩展性,同时还可以更好地利用现有的开源库和工具来加速开发过程。

优势总结:

  • 版本统一化管理

  • 各项目各自独立,维护的时候方便

  • 一个模块出现宕机,也不会影响其他模块

2、多模块拆解示例

前言

ERP项目通常包含多个业务模块,可以使用Maven的多模块项目结构来组织这些模块。以下是如何根据业务模块进行Maven多模块拆分的步骤:

  1. 创建父项目,作为所有模块的容器。
  2. 在父项目中定义所有子模块的配置。
  3. 创建各个业务模块作为子项目,并在它们的pom.xml中声明它们的父项目。

以下是示例代码:

父项目的pom.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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yourcompany.erp</groupId>
    <artifactId>erp-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
 
    <modules>
        <module>erp-module-inventory</module>
        <module>erp-module-sales</module>
        <module>erp-module-finance</module>
        <!-- 其他模块 -->
    </modules>
 
    <!-- 父POM中的其他配置 -->
</project>

子模块的pom.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/maven-v4_0_0.xsd">
    <parent>
        <groupId>com.yourcompany.erp</groupId>
        <artifactId>erp-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>erp-module-inventory</artifactId>
 
    <!-- 子模块的其他配置 -->
</project>

在这个例子中,我们创建了一个名为erp-parent的父项目,它包含了三个子模块:

erp-module-inventory(库存管理)

erp-module-sales(销售管理)

erp-module-finance(财务管理)

每个子模块都通过<parent>元素声明它们的父项目,这样Maven就可以理解模块之间的层次关系。

3、 拆分规则

对于多模块Maven工程,其拆分规则应根据具体情况和项目需求来确定。以下是一些常用的拆分规则:

  • 按业务模块划分: 将一个大型系统按照不同的业务模块进行划分,每个模块可以独立开发、测试、部署和维护。比如,对于一个电商系统,可以将商品管理、订单管理、用户管理等业务模块单独拆分成不同的子模块。

  • 按功能模块划分: 将一个系统按照不同的功能模块进行划分,每个模块负责完成一个特定的功能,比如认证、授权、缓存、搜索等。

  • 按技术组件划分: 将一个系统按照不同的技术组件进行划分,每个模块可以包含一个或多个技术组件,比如数据库连接、消息队列、缓存框架等。

  • 按层次划分: 将一个系统按照不同的层次进行划分,每个模块可以包含一个或多个层次,比如数据访问层、服务层、控制层等。

  • 混合划分: 可以将上述的任意两种或多种方式结合起来使用,以达到更好的代码复用、可维护性和可扩展性。

无论采用何种拆分规则,都需要注意以下几点:

拆分后的子模块应该具有独立的功能和职责,能够单独进行测试、构建和部署。

子模块之间应该避免出现循环依赖,否则会导致构建失败和部署异常。

子模块之间的接口应该设计良好,遵守面向接口编程的原则,以提高代码的复用性和灵活性。

4、 创建多模块的步骤

父项目要添加

<packaging>pom</packaging>  1.pom  2.jar 3.war 

规则:

父工程

​ 子工程

​ 子子工程

5、 子模块没有启动类打包出错的解决办法

项目里包含的common或者utils之类的工具类子模块,只是提供给其他子模块引用,并不需要启动(没有main启动类)。但是父工程的pom文件引用了springboot的maven打包插件spring-boot-maven-plugin,即:

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

父子工程中的pom.xml中去除该配置。

然后在父工程中添加如下插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.1.0</version>
        </plugin>
    </plugins>
</build>
<properties>
    <java.version>1.8</java.version>
    <!-- 跳过测试 -->
    <skipTests>true</skipTests>
</properties>
6、 导入依赖

依赖示例:

<properties>
    <java.version>1.8</java.version>
    <mybatis-plus.version>3.0.5</mybatis-plus.version>
    <swagger.version>2.7.0</swagger.version>
    <commons-fileupload.version>1.3.1</commons-fileupload.version>
    <commons-io.version>2.6</commons-io.version>
    <httpclient.version>4.5.1</httpclient.version>
   
</properties>

<dependencyManagement>
    <dependencies>
        <!--Spring Cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${cloud-alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--mybatis-plus 持久层-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!--文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${commons-fileupload.version}</version>
        </dependency>

        <!--commons-io-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons-io.version}</version>
        </dependency>

        <!--httpclient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpclient.version}</version>
        </dependency>


    </dependencies>
</dependencyManagement>
7、Maven中依赖的域(了解)

在Maven中依赖的域有: compile、provided、runtime、system、test、import。

依赖范围(Scope)编译classpath测试classpath运行时classpath传递性说明
compileYYYYspring-core
test-Y--junit
providedYY--servlet-api
runtime-YYYjdbc驱动
systemYY--本地jar包
  • compile(默认)

当依赖的scope为compile的时候,那么当前这个依赖的包,会在编译的时候被加入进来,并且在打包(mvn package)的时候也会被加入进来。

编译范围有效,在编译与打包时都会加入进去。

  • test

当依赖的scope为test的时候,指的的是在测试范围有效,在编译与打包的时候都不会使用这个依赖。

  • provided

当依赖的scope为provided的时候,在编译和测试的时候有效,在执行(mvn package)进行打包时不会加入。比如, 我们开发一个web应用,在编译时我们需要依赖servlet-api.jar,但是在运行时我们不需要该 jar包,因为这个jar 包已由web服务器提供,如果在打包时又被加入进去,那么就可能产生冲突。此时我们就可以使用 provided 进行范围修饰。

  • runtime

当依赖的scope为runtime的时候,在运行的时候才会依赖,在编译的时候不会依赖。比如,在编译的时候我们不需要JDBC API的jar包,而在运行的时候我们才需

要JDBC驱动包。就可以使用runtime修饰。

  • system

与provided相同,不过被依赖项不会从maven仓库获取,而是从本地文件系统拿,需要配合systemPath属性使用。比如:

<dependency>
    <groupId>org.open</groupId>
    <artifactId>open-core</artifactId>
    <version>1.5</version>
    <scope>system</scope>
    <systemPath>${basedir}/WebContent/WEB-INF/lib/open-core.jar</systemPath>
</dependency>
  • import

maven多模块项目结构中,可以使用parent 定义父项目,实现从父项目中继承依赖。但maven只能单继承,即一个项目只能使用一个parent标签定义父项目。

maven2.9之后的版本引入了一个新的功能,可以实现依赖上的多重继承。这个功能可以将依赖配置复杂的pom文件拆分成多个独立的pom文件。这样处理

可以使得maven的pom配置更加简洁,同时可以复用这些pom依赖。

比如,我们在开发spring boot 项目的时候,pom中会有如下配置:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.3.RELEASE</version>
</parent>

但是,如果该项目是个maven子模块的话,就会出现问题。由于maven类似java是单继承,不能有两个parent,现在标签已经用来引用父

模块,现在又用来引用springboot,就会产生冲突。

那解决办法就是: 使用dependencyManagement引入dependency,并且把scope属性改为import。如下:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

注意:scope的import 属性只能在 中使用,表示从其它的pom文件中导入dependency配置。

8、idea同时启动多个服务模块

进行配置将以下代码写入.idea目录下的workspase.xml的RunDashboard节点下

<option name="configurationTypes">
      <set>
        <option value="SpringBootApplicationConfigurationType" />
      </set>
</option>

配置完成后,重启idea

<component name="RunDashboard">
    <option name="configurationTypes">
        <set>
            <option value="SpringBootApplicationConfigurationType" />
        </set>
    </option>
    <option name="ruleStates">
        <list>
            <RuleState>
                <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
            </RuleState>
            <RuleState>
                <option name="name" value="StatusDashboardGroupingRule" />
            </RuleState>
        </list>
    </option>
</component>
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值