学后端,最容易卡在两个阶段:

  • 会写接口,但说不清一个后端系统“整体是怎么运转的”

  • 会用框架,但不知道“哪些代码属于系统能力,哪些属于业务能力”

真正开始“像后端工程师一样思考”,一定要做一件事:
👉 把一次请求从 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 层只做四件事:

  1. 接协议(HTTP)
  2. 参数校验
  3. DTO → Command
  4. 调用 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

👉 变化不扩散,系统才可演进。

六、最小后端服务的“工程验收标准”

一个合格的最小后端服务,至少满足:

  1.  能启动
  2.  有清晰分层
  3.  有真实数据库
  4.  有事务接口
  5.  至少一个多表业务
  6.  SQL 能 explain
  7.  你能脱离代码,画出完整链路

如果这些都成立:

👉 你已经真正“入门后端工程”。

七、最容易犯的几个错误

❌ Controller 写业务
❌ Service 变成 DAO 转发器
❌ Domain 只剩下 get/set
❌ SQL 里堆业务规则
❌ 事务散落各层

这些,都会直接导致:

👉 “能跑,但不可维护”。

八、总结一句话

后端学习的真正分水岭,不是会不会写接口,而是:

👉 你能否清楚地区分:

  • 系统入口
  • 系统调度
  • 业务核心
  • 技术实现

并让它们在工程中,各归其位。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐