spring一个项目多个模块聚合打包问题解决方案
文章目录
- 1.问题描述:
- 2.解决方案
- 一、创建聚合父工程
- 二、创建子模块(module)
- 三、编写子模块代码
- 1.模块1(demo-one)
- 2.模块2(demo-tow)
- 四、创建聚合模块 (demo-starter)
- 1. starter聚合模块pom配置 (依赖子模块很重要)
- 五、打包测试
- 六、最后的最后 测试一下效果
1.问题描述:
最近遇到个需求,针对后端解耦模块较多的项目,想在云端启动时简洁些只启动一个jar文件的情景。
1)解耦较细多个子module一个项目下
2)只想打到一个包启动一次
3)原解耦架构不想打破、不想重构
2.解决方案
针对此问题spring原生自带处理方式,下面写个demo
一、创建聚合父工程
1.首先使用 Spring Initializr 来快速创建好一个Maven工程。然后删除无关的文件,只需保留pom.xml 文件。这里命名 demo-Project。

2.然后在 pom.xml 里面声明该父工程包含的子模块。(其它信息就不逐一讲述了,诸如继承SpringBoot官方父工程以及统一依赖管理 请查看下面的注释说明)
<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.16</version><relativePath/> <!-- lookup parent from repository --></parent><packaging>pom</packaging><groupId>com.example</groupId><artifactId>demo-Project</artifactId><version>0.0.1-SNAPSHOT</version><name>demo-Project</name><description>demo-Project</description><modules><module>demo-starter</module><module>demo-one</module><module>demo-tow</module></modules><properties><java.version>1.8</java.version></properties><dependencies><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></dependency></dependencies><!-- <build>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>--></project>
二、创建子模块(module)
分别调整它们的pom.xml 以继承上面的父工程。
例如demo-one模块的pom.xml 需要改造成这样:
<?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><parent><groupId>com.example</groupId><artifactId>demo-Project</artifactId><version>0.0.1-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><groupId>com.example</groupId><artifactId>demo-one</artifactId><version>0.0.1-SNAPSHOT</version><name>demo-one</name><description>demo-one</description><properties><java.version>8</java.version></properties><dependencies><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></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><!-- <build>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>--></project>
三、编写子模块代码

注:正常是控制层、业务层、数据层等的解耦,目前是简单多业务架构模式假设每模块里都有自己的service、entity、repo、service等层次代码只是demo简单写了。
1.模块1(demo-one)
启动类 :DemoOneApplication.java (demo-one)
package com.example.demoone;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoOneApplication {public static void main(String[] args) {SpringApplication.run(DemoOneApplication.class, args);}}
控制器:ConTeone.java (demo-one)
package com.example.demoone.controler;import com.example.demoone.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class ConTeone {@AutowiredUser user;@PostMapping("/contest1")public String test1(){return "test1";}@PostMapping("/contest1/onebean")public User test2(){return user;}
}
javabean User类:
package com.example.demoone.bean;import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;import java.io.Serializable;@Data
@Component
@ConfigurationProperties(prefix = "user")
@JsonSerialize
public class User{String username;String password;
}
配置文件:application.yml (demo-one)
server:port: 8081user:username: adminpassword: admin
spring:profiles:active: true
2.模块2(demo-tow)
启动类 :DemoTowApplication.java (demo-tow)
package com.example.demotow;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoTowApplication {public static void main(String[] args) {SpringApplication.run(DemoTowApplication.class, args);}}
控制器:Contest.java (demo-tow)
package com.example.demotow.controler;import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class Contest {@PostMapping("/contest2")public String testTow(){return "test2";}
}
配置文件:application.yml (demo-tow) 这个不配了没写特殊的东西,只是在demo-one里写了从yml配置好做演示。
四、创建聚合模块 (demo-starter)
创建聚合模块 它的pom.xml 以继承上面的父工程。代码为普通的spring-web的项目即可,拥有初始的 启动类即可。但是启动类需要开启包路径扫描。
要求:
1)开启包扫描;
2)要继承 子模块demo-one、demo-tow;
3)要有打包插件配置 spring-boot-maven-plugin;
4)其他子模块需要去掉打包插件 这很重要。
1. starter聚合模块pom配置 (依赖子模块很重要)
下图依赖了两个子模块。

下图的打包配置,最简单的配置即可,当然看项目而定 有复杂需求按自己实际配置即可。

<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.16</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo-starter</artifactId><version>0.0.1-SNAPSHOT</version><name>demo-starter</name><description>demo-starter</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>com.example</groupId><artifactId>demo-one</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.example</groupId><artifactId>demo-tow</artifactId><version>0.0.1-SNAPSHOT</version></dependency><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></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2.starter聚合模块开启包扫描 (很重要)

特别注意:如果子模块包路径和启动类的根路径一致,不加上述注解也可,我这就是一样的但是为了演示所以还是配置了。
五、打包测试
万事俱备直接打包测试即可了。
在父pom的项目路径下打包
mvn clean package

打出来的包 在 demo-starter所在的路径里,当然运行 install 在本地仓库找也可;发布制品库的话直接发布上去的也是 demo-starter;

六、最后的最后 测试一下效果
启动 demo-starter
java -jar .\demo-starter-0.0.1-SNAPSHOT.jar

demo-one的 返回User的接口

demo-one 的返回string的接口

demo-tow的返回string的接口

相关文章:
spring一个项目多个模块聚合打包问题解决方案
文章目录 1.问题描述:2.解决方案一、创建聚合父工程二、创建子模块(module)三、编写子模块代码1.模块1(demo-one)2.模块2(demo-tow) 四、创建聚合模块 (demo-starter)1. …...
Linux设备树(Device Tree)何时被解析
Linux设备树(Device Tree)是在内核启动阶段就会被解析。当 Linux 内核启动的时候,它会读取设备树文件(dtb文件)并根据里面的信息来组织设备、加载驱动等。在驱动代码里,通常我们是在驱动初始化(…...
【Elasticsearch】数据简单操作(二)
简介:Elasticsearch(ES)是一个开源的分布式搜索和分析引擎,用于快速存储、搜索和分析大量数据。它具有高性能、可扩展性和灵活性的特点,被广泛用于构建实时搜索、日志分析、数据可视化等应用。 本文主要介绍ES索引的操…...
4 vCPU 实例达成 100 万 JSON API 请求/秒的优化实践
“性能工程” (Performance engineering)是个日渐流行的概念。顾名思义“性能工程”是包含在系统开发生命周期中所应用的一个技术分支,其目的就是确保满足非功能性的性能需求,例如:性能、可靠性等。由于现代软件系统变…...
呼叫中心系统有什么优势
在随着企业的管理水平也在不断提高。企业经营管理中所涉及到的各种复杂问题都有逐渐凸显出来。传统的呼叫中心已无法满足企业服务需求和客户满意度变化的要求。因此通过呼叫中心系统将企业业务流程和数据整合起来进行管理和运营已经成为目前企业管理领域中较为流行和成熟之选。…...
如何在linux操作系统下安装nvm
本文主要介绍如何在linux操作系统下安装nvm,如果想知道nvm如何在windows操作系统下使用,请参考文章如何通过nvm管理多个nodejs版本_nvm 查看所有node版本-CSDN博客。 1、nvm下载 nvm全称Node Version Manager,即Node版本管理器。访问官网地址…...
Linux 入门:基本指令
本篇文章来介绍我们在初学Linux时可以会碰倒的一些基本指令,让我们对这些指令有一个基本的了解。 目录 01. ls 指令 02. pwd 命令 03. cd 指令 04. touch 指令 05. mkdir 指令(重要) 06. rmdir指令 && rm 指令(重…...
IP转地理位置:探讨技术与应用
IP地址是互联网上设备的唯一标识符,而将IP地址转换为地理位置信息是网络管理、安全监控和市场定位等领域中的一项重要任务。本文将深入探讨IP转地理位置的技术原理和各种应用场景。 IP地址与地理位置 IP地址(Internet Protocol Address)是一…...
关于埋点上报
一、埋点上报结构包含哪些? 埋点上报结构一般包含以下信息: 事件名称:标识上报的是哪个事件,例如“注册成功”或“点击按钮”等。事件发生时间:记录事件发生的时间戳。用户ID:标识事件所属的用户。设备信息…...
最新博客园图片上传接口,模拟实现图片上传
简单看了一下博客园的图片上传接口,可以拿来做图床工具,仅供参考学习,请勿滥用。 1、实例代码 #!/usr/bin/python # -*- coding: UTF-8 -*- """ author: Roc-xb """import requestsurl "https://uplo…...
ROS2 从头开始:第 08/8回 - 使用 ROS2 生命周期节点简化机器人软件组件管理
一、说明 欢迎来到我在 ROS2 上的系列的第八部分。对于那些可能不熟悉该系列的人,我已经涵盖了一系列主题,包括 ROS2 简介、如何创建发布者和订阅者、自定义消息和服务创建、...
Vue组件库Element
目录 Vue组件库ElementElement简介Element快速入门环境配置Element常用组件Table表格Table表格演示Table表格属性详解 Pagination分页Pagination分页演示Pagination分页属性详解Pagination分页事件详解 Dialog对话框Dialog对话框组件演示Dialog对话框属性详解 Form表单Form表单…...
broadcast自动扩展
broadcast: 1、能够进行维度扩展,是自动的2、在扩展的时候不需要拷贝数据要点: - 从最小的维度开始匹配,如果前面没有维度了,在前面插入一个新的维度。- 插入的新维度size是1,再将其扩展为与目标相同大小si…...
【Pm4py第七讲】关于visualization
本节用于介绍pm4py中的可视化函数,包括可视化bpmn、petri、性能图谱、变迁系统等。 1.函数概述 本次主要介绍Pm4py中一些常见的可视化函数,总览如下表: 函数名说明view_alignments(log, aligned_traces[, format])可视化对齐方法 view_bpmn(…...
通过 BigQuery 中的 11 个新链增强 Google Cloud 的区块链数据服务
2018 年初,Google Cloud 与社区合作,通过BigQuery 公共数据集实现区块链数据民主化;2019 年,又扩展了六个数据集;今天,我们在 BigQuery 公共数据集中添加了 11 个最受欢迎的区块链预览版。我们也在对该程序…...
C++笔记之文档术语——将可调用对象作为函数参数
C笔记之文档术语——将可调用对象作为函数参数 相关博文:C笔记之函数对象functors与可调用对象 文章目录 C笔记之文档术语——将可调用对象作为函数参数1.在函数参数中传递可调用对象2.‘在参数中传入可调用对象’和‘将可调用对象作为函数参数’哪个描述更加专业…...
【Android知识笔记】FrameWork中的设计模式
一、FrameWork中有哪些设计巧妙之处 例如: Binder调用,模糊进程边界: 屏蔽跨进程IPC通信的细节,让开发者把精力放在业务上面,无需关心进程之间的通信。Bitmap大图传输,高性能: 只传递Binder句柄,到目标进程后做内存映射,不用做大量数据拷贝,速度非常快。Zygote创建进…...
机器学习西瓜书+南瓜书吃瓜教程第三章学习笔记
本次学习为周老师的机器学习西瓜书谢老师南瓜书Datawhale视频 视频地址 下面为本人的学习笔记,最近很忙还没学多少,之后补!!! u1s1,边看视频边自己手推一遍真的清楚很多,强烈推荐自己手推虽然花…...
JUnit5单元测试提示“Not tests were found”错误
JUnit5单元测试提示“Not tests were found”错误,如下图所示: 或者 问题解析: 1)使用Test注解时,不能有返回值; 2)使用Test注解时,不能使用private关键字; 存在以上情…...
C++ -- IO流
目录 C语言的输入与输出 CIO流 C标准IO流 C文件IO流 文件常见的打开方式如下 以二进制的形式操作文件 以文本的形式操作文件 读写结构体 stringstream的简单介绍 C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
