一个最小后端服务的工程结构拆解——从 Controller 到数据库的全链路视角
本文通过构建"最小可运行后端服务",剖析了标准后端请求的完整处理链路。文章将后端系统划分为接口适配层、业务流程编排层、业务核心层和基础设施实现层四个层级,并以"创建用户+初始化账户"为例,详细展示了请求从Controller到数据库的全流程。重点强调各层的职责边界:Controller负责协议适配,Application层编排流程,Domain层专注业务规则
学后端,最容易卡在两个阶段:
会写接口,但说不清一个后端系统“整体是怎么运转的”
会用框架,但不知道“哪些代码属于系统能力,哪些属于业务能力”
真正开始“像后端工程师一样思考”,一定要做一件事:
👉 把一次请求从 Controller 进来,到最终落库的完整链路,在脑子里拆清楚。这篇文章,用一个“最小可运行后端服务”为例,从工程结构角度,拆解一次标准后端请求的完整链路。
一、什么是“最小后端服务”?
这里说的“最小”,不是 demo,而是:
👉 具备真实后端系统基本特征的最小闭环。
至少包含:
- 可启动服务
- 清晰分层
- 真实数据库
- 多表操作
- 事务边界
- SQL 可解释
也就是说:
👉 麻雀虽小,但五脏俱全。
二、最小后端服务的工程结构
一个标准、可演进的最小工程,可以抽象成四层:
interfaces/ 接口与协议适配层
application/ 业务流程编排层
domain/ 业务核心层
infrastructure/ 基础设施实现层
展开看:
interfaces/
http/controller
http/dto
http/vo
http/assembler
application/
service
command / query
domain/
model
service
repository (接口)
infrastructure/
persistence (repository实现 / mapper / dao)
client
config
👉 这是现代后端系统最稳定的一种“骨架结构”。
三、从 Controller 到数据库:一次请求到底经历了什么?
我们以一个典型场景为例:
👉 “创建用户 + 初始化账户信息”
这是一个天然的多表 + 事务场景。
① Controller:系统的入口层
示例:
@PostMapping("/users")
public UserVO createUser(@RequestBody @Valid CreateUserRequest dto) {
CreateUserCommand command = userAssembler.toCommand(dto);
User user = userApplicationService.createUser(command);
return userAssembler.toVO(user);
}
Controller 层只做四件事:
- 接协议(HTTP)
- 参数校验
- DTO → Command
- 调用 Application 层
👉 它不关心数据库,不关心事务,不承载业务规则。
它的本质角色是:
👉 系统的“协议适配器”。
② Application Service:系统的调度中枢
@Transactional
public User createUser(CreateUserCommand cmd) {
User user = User.create(cmd);
userRepository.save(user);
Account account = Account.initFor(user.getId());
accountRepository.save(account);
return user;
}
Application 层关心的是:
- 业务流程怎么走
- 调哪些领域对象
- 调哪些仓储
- 事务边界在哪
👉 这是“系统如何运转”的地方。
特征非常明显:
- 方法通常是“流程型”
- 经常是多仓储调用
- 事务几乎都在这一层
👉 Application 层 = 用例编排器。
③ Domain:系统真正的核心
public class User {
private Long id;
private String phone;
public static User create(CreateUserCommand cmd) {
if (!PhoneValidator.valid(cmd.getPhone())) {
throw new BizException("手机号非法");
}
return new User(cmd.getPhone());
}
}
Domain 层只关心一件事:
👉 业务本身是否成立。
它通常包含:
- 业务规则
- 状态变化
- 不变量校验
- 领域行为
关键特征:
- 不依赖 Spring
- 不依赖 MyBatis
- 不关心 HTTP
- 可脱离框架单测
👉 Domain 决定系统的“业务上限”。
④ Repository 接口:领域与基础设施的边界
public interface UserRepository {
void save(User user);
Optional<User> findById(Long id);
}
这里定义的是:
👉 “领域需要什么数据能力”
而不是:
👉 “数据库怎么查”。
⑤ Infrastructure:数据真正落地的地方
@Repository
public class UserRepositoryImpl implements UserRepository {
@Override
public void save(User user) {
userMapper.insert(user);
}
}
这一层负责:
- SQL
- ORM
- 表结构
- 索引
- 中间件
👉 它解决的是:系统如何实现,而不是系统是什么。
⑥ 最终:SQL 与数据库
insert into user(id, phone, create_time) values(?,?,?)
在这里,后端系统真正接触:
- 索引
- 锁
- 事务
- 执行计划
- 磁盘与内存
👉 这已经是系统资源层。
四、一次请求的完整链路图
HTTP Request
↓
Controller (协议适配 / 校验 / DTO)
↓
Application Service (流程编排 / 事务)
↓
Domain (业务规则 / 状态)
↓
Repository 接口
↓
Infrastructure 实现 (ORM / SQL)
↓
Database (索引 / 执行计划 / 锁 / 事务)
👉 这条链路,是后端工程师必须“条件反射级别”掌握的结构。
五、为什么一定要这样分?
因为后端系统的核心矛盾不是写接口,而是:
- 业务会变
- 数据源会变
- 中间件会变
- 访问方式会变
分层的真正价值是:
👉 让变化被限制在对应层内。
例如:
- 接口从 HTTP 换成 RPC → 主要影响 Interface
- 数据库从 MySQL 换成 TiDB → 主要影响 Infrastructure
- 业务规则变化 → 主要影响 Domain
- 业务流程变化 → 主要影响 Application
👉 变化不扩散,系统才可演进。
六、最小后端服务的“工程验收标准”
一个合格的最小后端服务,至少满足:
- 能启动
- 有清晰分层
- 有真实数据库
- 有事务接口
- 至少一个多表业务
- SQL 能 explain
- 你能脱离代码,画出完整链路
如果这些都成立:
👉 你已经真正“入门后端工程”。
七、最容易犯的几个错误
❌ Controller 写业务
❌ Service 变成 DAO 转发器
❌ Domain 只剩下 get/set
❌ SQL 里堆业务规则
❌ 事务散落各层
这些,都会直接导致:
👉 “能跑,但不可维护”。
八、总结一句话
后端学习的真正分水岭,不是会不会写接口,而是:
👉 你能否清楚地区分:
- 系统入口
- 系统调度
- 业务核心
- 技术实现
并让它们在工程中,各归其位。
更多推荐


所有评论(0)