news 2026/6/11 11:05:59

告别“大泥球”:我在 Spring Boot 单体架构中实践的模块化隔离

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
告别“大泥球”:我在 Spring Boot 单体架构中实践的模块化隔离

前言:为什么我没选微服务?

经常有同行问我:“你们的网优系统业务这么复杂,为什么不拆微服务?”

我的回答很直接:因为我们的核心痛点不是“并发扩展”,而是“逻辑闭环”。

在电信网络优化领域,一个“天线接反”的判断,可能同时涉及告警数据、MR(测量报告)采样、工参地理信息以及历史性能趋势。如果把这些强行拆成四个微服务,光是处理分布式事务和链路追踪,就能把团队拖垮。

但这不代表我们可以容忍代码耦合。在 通信网络优化与分析平台 的性能子系统中,我坚持推行一种**“物理隔离、逻辑内聚”**的单体模块化策略。今天,我想抛开那些高大上的理论,聊聊我们是怎么在 Java 生态上,把代码治理得井井有条的。


一、 拒绝“水平分层”的陷阱

传统的 MVC 教程喜欢教你:所有 Controller 放一起,所有 Service 放一起。结果就是,controllers文件夹里塞了 50 个文件,你想找个“PCI 规划”的代码,得在一堆 Alarm,User、Log控制器里翻半天。

通信网络优化与分析平台中,我强制要求按业务域垂直切分(Package by Feature)

1. 目录结构的重构

我们不再使用扁平的包结构,而是采用垂直切片:

cn.starlinkcloud.crystal.noap.perf ├── antenna // 天线调整模块 │ ├── controller │ │ └── AntennaFeederAdjController.java │ ├── service │ │ ├── AntennaService.java │ │ └── impl │ │ └── AntennaServiceImpl.java │ ├── repository │ │ └── AntennaRepository.java │ └── model │ ├── entity │ │ └── AntennaReversedError.java │ └── dto │ └── AntennaQueryDTO.java ├── pci // PCI 规划模块 │ ├── controller │ │ └── PCIController.java │ ├── service │ │ └── ... │ └── ... └── common // 通用能力下沉 ├── excel │ └── ExcelExportHelper.java └── gis └── GridMergeHelper.java

原则:一个包(Package),就是一个完整业务场景的边界。它不应该去依赖其他无关业务的 Package。如果pci模块需要用到告警数据,它注入的是IAlarmService接口,而不是直接去查告警表。

2. 前端资源的模块化

在后端垂直切分的同时,前端(Vue/React)也采用类似的模块化结构:

  • src/views/antenna/index.vue:天线调整页面组件。
  • src/api/antenna.js:专门服务于天线模块的 Axios 请求封装。

效果:即使两个模块里都有initTable()函数,只要它们在不同的 Vue 组件或 JS 模块中,就不会打架。


二、 实体类不是数据库表的奴隶:DTO 与 Entity 分离

在 JPA/Hibernate 时代,很多人习惯搞一个巨大的@Entity类,把所有字段都塞进去,并直接返回给前端。

我反对这种做法。在网优领域,上下文不同,模型不同

1. 细分的领域对象

  • Entity 层:AlarmL4G.java对应数据库表,使用 JPA 注解。
  • DTO 层AlarmListDTO只包含列表页需要的几个关键字段(小区名、告警码、时间)。
  • VO 层AntennaReversedErrorVO是经过算法计算后的“结果对象”,用于前端展示。

架构师视角:使用 MapStruct 进行对象转换,避免手动写 getter/setter。当你在代码里看到PCICheckRule.java时,你应该意识到这是一条规则,而不是一行 SQL 记录。


三、 接口隔离与依赖注入:Spring 的核心灵魂

虽然现在是单体,但我要求所有 Service 必须定义接口,并使用@Autowired或构造函数注入。

为什么?

  1. 单元测试能跑通:在测试HealthDiagnosisController时,我可以@MockBeanIHealthDiagnosisService,不用启动数据库,测试速度从分钟级降到秒级。
  2. 随时准备“剥离”:如果哪天老板说,“这个 PCI 算法太耗 CPU,我们要把它独立成一个 Python 微服务”,我只需要重写IPCIService的实现类,让它去调 RestTemplate/WebClient,而 Controller 层的代码一行都不用改

这就是依赖倒置带来的底气。


四、 通用能力下沉:别重复造轮子

在每个模块里写 Excel 导出?别逗了。

我把所有跨模块的通用逻辑,全部扔进common模块或 Starter:

1. 重型计算的下沉:GridMergeHelper

电信网优系统离不开 GIS。我们将栅格合并算法封装在common-gis模块中:

  • 并行计算:利用 Java 8ParallelStreamCompletableFuture优化多点聚合。
  • 空间索引:引入 JTS (Java Topology Suite) 库处理地理围栏和点位落入计算。

2. IO 密集型操作的封装:ExcelExportUnity

  • 流式写入:使用EasyExcel(Alibaba) ,避免 OOM。
  • 注解驱动:通过@ExcelProperty定义列头,实现声明式导出。

使用场景: 无论是 AlarmStatisticsController 还是 VoltePoorQualityCellAnalysisController,只需调用同一行代码:

return ExcelExportHelper.export(response, dataList, "告警统计表.xlsx");

五、 多主题支持:前端工程化的胜利

在 Spring Boot 后端,我们不再处理 CSS 文件。多主题支持完全交给前端工程化(Webpack/Vite)处理。

  • CSS Variables:使用 CSS 变量定义颜色主题。
  • 动态加载:根据用户配置,在前端入口文件动态引入theme-blue.csstheme-red.css

后端职责:只提供用户偏好配置的 API 接口,彻底解耦表现层与业务层。


六、 给维护者的真心话

如果你正在接手或维护类似 CNOAP 的 Spring Boot 系统,我有三条建议:

  1. 严守包边界:不要为了方便,在AntennaController里直接@Autowired一个PCIRepository。请走 Service 接口。一旦开了这个口子,模块化就名存实亡。
  2. 统一异常处理:使用@RestControllerAdvice全局捕获异常,返回统一的 JSON 格式,避免每个 Controller 都写 try-catch。
  3. 关注 Common 模块:随着系统运行,Common 模块容易变成垃圾堆。定期审查,把那些只被一个模块使用的“通用”代码,移回它所属的业务模块。真正的通用,是被三个以上模块依赖。

结语

架构没有银弹。微服务很好,但对于强逻辑关联、重算法计算的网优系统,模块化的 Spring Boot 单体依然是性价比最高的选择。

我们不追求技术的时髦,我们追求的是:当业务人员问“为什么这个小区 PCI 冲突没算出来”时,我们能要在 5 分钟内定位到代码,而不是在 5 个微服务的日志里迷路。

版权声明:本文为原创文章,转载请注明出处。商业转载请联系作者获得授权。

作者简介:系统架构师,专注于电信大数据平台架构设计与运维。目前负责日均处理2亿条消息的ucp平台,擅长分布式系统设计、消息中间件运维和高可用架构。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 11:01:32

题解:AtCoder AT_awc0088_b Bus Tour Group Division

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大…

作者头像 李华
网站建设 2026/6/11 11:01:31

硬件设计笔记:CK6869D蓝牙TWS对箱播放器原理图与PCB布局方案

前言大家好,我是原厂硬件工程师,长期负责蓝牙音频SOC的方案适配、电路标准化设计与TWS对箱产品硬件调试。在便携立体声音频设备中,TWS对箱凭借无线互联、左右声道独立发声、立体声场效果,成为主流消费品类。很多工程师在开发低成本…

作者头像 李华
网站建设 2026/6/11 10:58:42

Typora插件开发指南:从零打造IDE级写作环境

Typora在Markdown编辑器中的地位毋庸置疑。极简的设计、流畅的体验、即时渲染的优雅,让它成为无数技术写作者的首选。但许多用户不知道的是,Typora背后隐藏着一套完整的插件扩展体系。通过这套体系,你可以为Typora添加任何你想要的功能&#…

作者头像 李华
网站建设 2026/6/11 10:53:07

跨平台MSG邮件查看器:3步免费解决Outlook格式困扰的终极指南

跨平台MSG邮件查看器:3步免费解决Outlook格式困扰的终极指南 【免费下载链接】MsgViewer MsgViewer is email-viewer utility for .msg e-mail messages, implemented in pure Java. MsgViewer works on Windows/Linux/Mac Platforms. Also provides a java api to …

作者头像 李华