尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Spring Boot + MyBatis 多模块项目中,如何优雅完成一个增量需求

Spring Boot + MyBatis 多模块项目中,如何优雅完成一个增量需求
📅 发布时间:2026/6/26 5:12:28

摘要

在老系统中做需求,最怕的不是写代码,而是不清楚应该改哪里、复用哪里、绕开哪里。本文结合一个续期管理后台中的“规则中心配置页”需求,聊聊在 Spring Boot + MyBatis 多模块项目里,如何用较小改动完成一次稳定的增量开发。

1. 背景

很多企业项目不是从零开始的,而是在已有系统上不断迭代。常见结构大概是:
project-root
├── project-api
├── project-common
├── project-core
├── project-provider
├── project-server
└── project-web
这类项目通常有几个特点:
Controller 层在 web 模块;
业务 Service 在 core 模块;
DTO、Entity、Param 在 api 模块;
通用枚举、工具类在 common 模块;
外部系统调用或消息处理在 provider/server 模块;
MyBatis Mapper 和 XML 通常集中在 core。
如果新需求一上来就大改底层逻辑,风险会非常高。更稳妥的方式是:先定位现有链路,再基于现有架构做增量封装。

2. 增量需求的拆解方式

以“新增一个配置页”为例,页面可能包含:
配置列表查询;
新增配置;
删除配置;
批量提交;
操作历史;
异常清单下载;
权限控制。
后端可以拆成以下几层:
Controller
↓
Application Service
↓
Domain / Legacy Service
↓
Mapper / External Provider
关键点是:新 Service 不一定要重写业务逻辑,而是作为“编排层”存在。
例如:

publicinterfaceDataConfigService{List<ProductOption>listProductOptions(Stringkeyword);voidaddConfig(IntegerproductId,StringproductName,LongoperatorId);voiddeleteConfig(IntegerproductId,LongoperatorId);BatchResultbatchRepair(Stringids,StringoperatorNo,StringoperatorName);PageResult<ImportRecordDTO>pageRecords(RecordQueryquery);}

这个接口并不关心底层数据到底来自老表、新表、外部接口还是消息处理链路。它的职责是把页面需要的能力整理成稳定接口。

3. Controller 层只做三件事

在老项目里,Controller 很容易越写越厚。我的经验是尽量让 Controller 只做三件事:
接收参数;
获取当前操作人;
调用 Service 并返回统一结果。
示例:

@PostMapping("/config/add")publicResult<Void>addConfig(@RequestBodyConfigRequestrequest,HttpServletRequestservletRequest){Employeeemployee=getCurrentEmployee(servletRequest);dataConfigService.addConfig(request.getProductId(),request.getProductName(),Long.valueOf(employee.getId()));returnResult.success();}

这样做的好处是清晰:
参数校验在 Service 中统一处理;
操作人信息不散落在各处;
Controller 不感知底层业务细节;
后续单测更容易写。

4. 复用旧逻辑,而不是复制旧逻辑

老系统里常常已经有一些能力,比如:
根据投保单号查询主数据;
更新保单状态;
调用外部系统补齐数据;
写操作日志;
发送消息通知;
查询配置。
新增功能时,优先考虑“调用已有 Service”,而不是把旧代码复制一份过来。
错误示例:

// 把旧逻辑复制到新 Service 中,后续两边都要维护privatevoidrepairData(Longid){// 一大段复制来的老逻辑}

更好的方式:

privatevoidrepairData(Longid){legacyRepairService.repairById(id);}如果旧逻辑粒度太粗,可以在外层做适配:privatevoidrepairOne(Longid){try{legacyService.repair(id);}catch(Exceptione){thrownewBusinessException(normalizeMessage(e.getMessage()));}}

这样新增功能就变成“业务编排”,不是“底层重写”。

5. 批处理要有记录和失败明细

批量提交类需求不要只返回一句“处理完成”。更实用的模型是:
导入记录表
├── 操作类型
├── 操作人
├── 总数
├── 成功数
├── 失败数
├── 状态
└── 操作时间

失败明细表
├── 记录ID
├── 业务单号
└── 失败原因
批处理伪代码:

privateBatchResultexecuteBatch(List<Long>ids,Processorprocessor){ImportRecordrecord=createRecord(ids.size());intsuccess=0;List<ImportError>errors=newArrayList<>();for(Longid:ids){try{processor.process(id);success++;}catch(Exceptione){errors.add(buildError(record.getId(),id,e.getMessage()));}}saveErrors(errors);updateRecord(record,success,errors.size());returnbuildResult(record);}

这个设计有两个明显优势:
用户知道每次操作的结果;
失败数据可以下载后继续排查。

6. 小结

在多模块老系统中做增量需求,重点不是“写更多代码”,而是“把新功能安放在合适的位置”。
建议遵循几个原则:
Controller 保持薄;
新增 Service 做编排;
复用旧业务链路;
Mapper 只承载必要查询;
批处理必须有历史记录;
权限点跟页面和按钮保持一致;
不做无关重构。
老系统改造最重要的是稳。能小步扩展,就不要大刀阔斧。

相关新闻

  • 大模型聚合 API 全网测速实测:延迟瓶颈拆解与商用平台落地对比
  • 2026年,400电话源头厂家哪个值得选?
  • 3分钟掌握WinAsar:Windows平台最轻量asar文件管理工具终极指南

最新新闻

  • MySQL性能怎么看?mysqld_exporter采集、告警与远程监控指南
  • WD5081,6.5V~90V,1A异步降压转换器,高集成度、低成本
  • 阿联酋原油出口恢复八成五,原油期货供应扰动与市场影响分析
  • NAS、网盘、本地电影太多,播放器怎么选?VidHub、Infuse、nPlayer、Jellyfin、Plex 适合谁?
  • Okbiye AI 写作数据分析模块:一键生成实证报告,破解社科论文数据处理难题
  • 2026年用Gemini镜像站解决Java微服务架构难题

日新闻

  • Qwen2.5-Turbo百万上下文实战指南:百炼平台长文本处理全解析
  • 怎么监控对标账号更新,2026年作者监控工作流,5款深度对比
  • EdgeRemover:专业级Windows Edge浏览器管理工具,彻底解决顽固软件卸载难题

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号