Files
test-repo/docs/zh-cn/appendix/4-server-and-backend/backend-project-architecture.md
T
sanbuphy df51f84ab5 docs: 重构 README 附录展示 & 新增多个附录交互组件
README 更新:
- 移除顶部 header.png 横幅图片
- 新增「附录知识库」板块,以 3×3 网格展示 9 大知识领域精选内容
- 附录链接指向部署版网站 (datawhalechina.github.io)
- 阶段表格新增「附录」行,突出 80+ 交互式专题
- 章节标题「新手入门 & PM」简化为「零基础入门」
- News 新增 2026-02-25 附录知识库更新条目

新增交互组件:
- 异步任务队列 (async-task-queues) 演示组件
- 文件存储 (file-storage) 演示组件
- 项目架构 (project-architecture) 演示组件
- 限流与背压 (rate-limiting) 演示组件
- 搜索引擎 (search-engines) 演示组件
- 计算机基础: AppLaunch/BiosUefi/OSBoot 等启动流程演示组件

新增附录文档:
- 前端项目架构 (frontend-project-architecture.md)
- 后端项目架构 (backend-project-architecture.md)

内容优化:
- 算法思维、数据结构、编程语言、调试艺术等多篇附录内容更新
- HTML/CSS 布局、请求旅程等前后端文档完善
- 附录索引页 (index.md) 同步更新
2026-02-25 12:22:49 +08:00

21 KiB
Raw Blame History

后端项目架构设计

::: tip 🎯 核心问题 API 越写越多,代码越来越乱,如何设计一个清晰、可维护的后端项目结构? 这就像问:你是把所有工具都扔进一个抽屉,还是按功能分类整理?好的项目架构能让团队协作更高效,让系统扩展更轻松。 :::


1. 为什么要关注后端项目架构?

1.1 从小脚本到大系统的演变

很多初学者刚开始写后端时,代码结构非常简单:

# app.py - 所有代码在一个文件
from flask import Flask, request, jsonify
import sqlite3

app = Flask(__name__)

@app.route('/users', methods=['GET'])
def get_users():
    conn = sqlite3.connect('db.sqlite')
    users = conn.execute('SELECT * FROM users').fetchall()
    return jsonify(users)

@app.route('/users', methods=['POST'])
def create_user():
    data = request.json
    conn = sqlite3.connect('db.sqlite')
    conn.execute('INSERT INTO users (name, email) VALUES (?, ?)',
                 (data['name'], data['email']))
    conn.commit()
    return jsonify({'message': 'User created'})

# 还有订单、商品、支付...所有接口都在这个文件

几百行代码搞定一切,简单直接。但随着业务发展,问题开始出现:

  • 接口多了:一个文件几千行,找代码像"考古"
  • 逻辑复杂了:业务规则散落在各处,修改容易遗漏
  • 数据库操作重复:到处写 SQL,改表结构要改几十处
  • 测试困难:代码耦合严重,单元测试难以编写

问题的本质:没有"章法",所有的逻辑都堆在一起,就像把所有的工具、零件、说明书都扔进一个抽屉。

1.2 好的架构像整理好的车间

想象一个整理好的工厂车间:

区域 功能 特点
原料区 存放原材料 分类摆放,标签清晰
加工区 生产加工 流水线作业,工序明确
质检区 质量检查 统一标准,严格把关
成品区 存放成品 整齐有序,易于出库
工具室 存放工具 按需借用,用完归还

好的后端架构就是把代码也这样组织:每一层只关心自己的职责,数据像流水一样在各层之间传递。

::: tip 💡 通俗比喻:餐厅后厨的组织 把后端系统想象成一家餐厅的后厨:

  • controllers/(出餐口) = 服务员接单:接收订单、核对信息、上菜
  • services/(厨师团队) = 厨师做菜:按照菜谱加工、协调各工序
  • repositories/(仓库管理) = 仓管取料:从仓库取食材、记录库存
  • models/(菜谱标准) = 菜谱定义:宫保鸡丁需要什么料、什么口味
  • utils/(工具柜) = 厨具存放:刀、勺、秤等通用工具

关键点:每个角色职责明确,不会越界。服务员不会自己炒菜,厨师不会擅自改菜谱。 :::


2. 经典分层架构详解

2.1 四层架构(Controller-Service-Repository-Model

最经典的后端分层架构如下:

my-backend-project/
├── src/
│   ├── controllers/          # 控制器层(Controller
│   │   ├── userController.js
│   │   ├── orderController.js
│   │   └── index.js
│   ├── services/             # 业务逻辑层(Service
│   │   ├── userService.js
│   │   ├── orderService.js
│   │   └── index.js
│   ├── repositories/         # 数据访问层(Repository/DAO
│   │   ├── userRepository.js
│   │   └── index.js
│   ├── models/               # 数据模型层(Model/Entity
│   │   ├── user.js
│   │   ├── order.js
│   │   └── index.js
│   ├── middlewares/          # 中间件
│   │   ├── auth.js
│   │   ├── errorHandler.js
│   │   └── validator.js
│   ├── utils/                # 工具函数
│   │   ├── logger.js
│   │   ├── response.js
│   │   └── validator.js
│   ├── config/               # 配置文件
│   │   ├── database.js
│   │   ├── redis.js
│   │   └── index.js
│   ├── routes/               # 路由定义
│   │   ├── userRoutes.js
│   │   ├── index.js
│   │   └── api.js
│   ├── jobs/ 或 workers/     # 定时任务/后台任务
│   │   └── emailWorker.js
│   ├── events/ 或 subscribers/ # 事件监听
│   │   └── userEvents.js
│   └── app.js                # 应用入口
├── tests/                    # 测试文件
│   ├── unit/
│   ├── integration/
│   └── e2e/
├── migrations/               # 数据库迁移
├── seeds/                    # 种子数据
├── docs/                     # 文档
├── .env                      # 环境变量
├── package.json
└── README.md

::: tip 📊 从图解中你能看到什么? 分层逻辑

┌─────────────────────────────────────────┐
│  Controller 层(控制器层)               │  ← 接待员:接收请求,返回响应
│  - 接收 HTTP 请求                        │
│  - 参数校验、权限检查                     │
│  - 调用 Service                         │
│  - 格式化响应                            │
├─────────────────────────────────────────┤
│  Service 层(业务逻辑层)                │  ← 厨师:处理核心业务
│  - 业务逻辑编排                          │
│  - 事务管理                              │
│  - 调用 Repository                      │
│  - 跨模块协调                            │
├─────────────────────────────────────────┤
│  Repository 层(数据访问层)             │  ← 仓管员:管理数据存取
│  - 数据库操作                            │
│  - ORM 封装                              │
│  - 查询构建                              │
├─────────────────────────────────────────┤
│  Model 层(数据模型层)                  │  ← 菜谱标准:定义数据结构
│  - 实体定义(Entity)                    │
│  - 类型定义                              │
│  - 业务规则验证                          │
└─────────────────────────────────────────┘

依赖方向

Controller → Service → Repository → Model
                ↓
         Middleware / Utils

上层依赖下层,下层不依赖上层。Model 是核心,所有层都可能依赖它。 :::

2.2 各层职责详解

Controller 层:请求的"接待员"

Controller 是系统的"门面",负责接收 HTTP 请求并返回响应。

职责

  • 接收和解析请求参数
  • 调用相应的 Service 处理业务
  • 格式化响应数据
  • 处理 HTTP 相关逻辑(状态码、Header 等)

不应该做的事

  • 直接操作数据库
  • 编写复杂业务逻辑
  • 处理事务

::: details 📝 Controller 代码示例(Node.js/Express

// controllers/userController.js
const userService = require('../services/userService')
const { success, error } = require('../utils/response')

class UserController {
  // 获取用户列表
  async list(req, res) {
    try {
      const { page = 1, limit = 10 } = req.query
      const users = await userService.getUsers({ page, limit })
      return success(res, users)
    } catch (err) {
      return error(res, err.message, 500)
    }
  }

  // 获取单个用户
  async getById(req, res) {
    try {
      const { id } = req.params
      const user = await userService.getUserById(id)
      if (!user) {
        return error(res, 'User not found', 404)
      }
      return success(res, user)
    } catch (err) {
      return error(res, err.message, 500)
    }
  }

  // 创建用户
  async create(req, res) {
    try {
      const userData = req.body
      const newUser = await userService.createUser(userData)
      return success(res, newUser, 201)
    } catch (err) {
      return error(res, err.message, 400)
    }
  }
}

module.exports = new UserController()

:::

Service 层:业务的"厨师"

Service 是系统的"大脑",包含核心业务逻辑。

职责

  • 实现业务规则和流程
  • 协调多个 Repository 完成复杂操作
  • 管理事务
  • 数据转换和计算

不应该做的事

  • 直接处理 HTTP 请求/响应
  • 直接操作数据库(通过 Repository)

::: details 📝 Service 代码示例

// services/userService.js
const userRepository = require('../repositories/userRepository')
const orderRepository = require('../repositories/orderRepository')
const emailService = require('./emailService')
const { hashPassword } = require('../utils/crypto')

class UserService {
  // 获取用户列表
  async getUsers({ page, limit }) {
    const offset = (page - 1) * limit
    const [users, total] = await Promise.all([
      userRepository.findAll({ limit, offset }),
      userRepository.count()
    ])
    
    return {
      data: users,
      pagination: {
        page,
        limit,
        total,
        totalPages: Math.ceil(total / limit)
      }
    }
  }

  // 获取用户详情(包含订单信息)
  async getUserById(id) {
    const user = await userRepository.findById(id)
    if (!user) return null
    
    // 获取用户订单统计
    const orderStats = await orderRepository.getStatsByUserId(id)
    
    return {
      ...user,
      orderStats
    }
  }

  // 创建用户(包含事务和邮件通知)
  async createUser(userData) {
    // 检查邮箱是否已存在
    const existingUser = await userRepository.findByEmail(userData.email)
    if (existingUser) {
      throw new Error('Email already exists')
    }

    // 密码加密
    const hashedPassword = await hashPassword(userData.password)
    
    // 创建用户
    const newUser = await userRepository.create({
      ...userData,
      password: hashedPassword
    })

    // 发送欢迎邮件(异步,不阻塞)
    emailService.sendWelcomeEmail(newUser.email).catch(console.error)

    return newUser
  }
}

module.exports = new UserService()

:::

Repository 层:数据的"仓管员"

Repository 负责所有与数据存储相关的操作。

职责

  • 数据库的增删改查
  • ORM 映射
  • 查询优化

不应该做的事

  • 包含业务逻辑
  • 处理事务(由 Service 控制)

::: details 📝 Repository 代码示例

// repositories/userRepository.js
const { User } = require('../models')

class UserRepository {
  // 查询所有用户
  async findAll({ limit, offset }) {
    return await User.findAll({
      limit,
      offset,
      attributes: { exclude: ['password'] }  // 不返回密码
    })
  }

  // 根据 ID 查询
  async findById(id) {
    return await User.findByPk(id, {
      attributes: { exclude: ['password'] }
    })
  }

  // 根据邮箱查询
  async findByEmail(email) {
    return await User.findOne({ where: { email } })
  }

  // 创建用户
  async create(data) {
    return await User.create(data)
  }

  // 更新用户
  async update(id, data) {
    const user = await User.findByPk(id)
    if (!user) return null
    return await user.update(data)
  }

  // 删除用户
  async delete(id) {
    const user = await User.findByPk(id)
    if (!user) return null
    await user.destroy()
    return true
  }

  // 统计用户数量
  async count() {
    return await User.count()
  }
}

module.exports = new UserRepository()

:::

Model 层:数据的"定义"

Model 定义数据结构和业务规则。

::: details 📝 Model 代码示例(Sequelize

// models/user.js
const { DataTypes } = require('sequelize')
const { sequelize } = require('../config/database')

const User = sequelize.define('User', {
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true
  },
  name: {
    type: DataTypes.STRING(100),
    allowNull: false,
    validate: {
      len: [2, 100]
    }
  },
  email: {
    type: DataTypes.STRING(255),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true
    }
  },
  password: {
    type: DataTypes.STRING(255),
    allowNull: false
  },
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'banned'),
    defaultValue: 'active'
  }
}, {
  tableName: 'users',
  timestamps: true,  // 自动添加 createdAt 和 updatedAt
  indexes: [
    { fields: ['email'] },
    { fields: ['status'] }
  ]
})

module.exports = User

:::


3. 其他重要目录

3.1 middlewares/ 中间件

中间件是请求处理流程中的"过滤器"。

middlewares/
├── auth.js                   # 认证中间件
├── errorHandler.js           # 错误处理
├── validator.js              # 参数校验
├── rateLimiter.js            # 限流
├── logger.js                 # 请求日志
└── cors.js                   # 跨域处理

::: details 📝 中间件示例

// middlewares/auth.js
const jwt = require('jsonwebtoken')

const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1]
  
  if (!token) {
    return res.status(401).json({ message: 'No token provided' })
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET)
    req.user = decoded
    next()
  } catch (err) {
    return res.status(401).json({ message: 'Invalid token' })
  }
}

module.exports = authMiddleware

:::

3.2 routes/ 路由

集中管理所有 API 路由。

// routes/userRoutes.js
const express = require('express')
const router = express.Router()
const userController = require('../controllers/userController')
const authMiddleware = require('../middlewares/auth')

// 公开路由
router.get('/', userController.list)
router.get('/:id', userController.getById)

// 需要认证的路由
router.post('/', authMiddleware, userController.create)
router.put('/:id', authMiddleware, userController.update)
router.delete('/:id', authMiddleware, userController.delete)

module.exports = router
// routes/index.js
const express = require('express')
const router = express.Router()

router.use('/users', require('./userRoutes'))
router.use('/orders', require('./orderRoutes'))
router.use('/products', require('./productRoutes'))

module.exports = router

3.3 config/ 配置

集中管理所有配置,支持多环境。

// config/index.js
const env = process.env.NODE_ENV || 'development'

const configs = {
  development: {
    port: 3000,
    database: {
      host: 'localhost',
      port: 5432,
      name: 'myapp_dev'
    },
    redis: {
      host: 'localhost',
      port: 6379
    }
  },
  production: {
    port: process.env.PORT || 80,
    database: {
      host: process.env.DB_HOST,
      port: process.env.DB_PORT,
      name: process.env.DB_NAME
    }
  }
}

module.exports = configs[env]

3.4 utils/ 工具

utils/
├── logger.js                 # 日志工具
├── response.js               # 响应封装
├── crypto.js                 # 加密解密
├── date.js                   # 日期处理
└── validator.js              # 验证工具

4. 按功能组织(Feature-based

对于中大型项目,可以采用按功能组织的方式:

src/
├── features/
│   ├── users/
│   │   ├── users.controller.js
│   │   ├── users.service.js
│   │   ├── users.repository.js
│   │   ├── users.model.js
│   │   ├── users.routes.js
│   │   ├── users.validator.js
│   │   └── index.js          # 统一导出
│   ├── orders/
│   │   ├── orders.controller.js
│   │   ├── orders.service.js
│   │   └── ...
│   └── products/
│       ├── products.controller.js
│       └── ...
├── shared/                   # 共享资源
│   ├── middlewares/
│   ├── utils/
│   └── config/
└── app.js

优点

  • 高内聚,一个功能的所有代码在一起
  • 便于团队协作,不同人负责不同 feature
  • 易于删除或重构

5. 知名开源项目的架构参考

5.1 Express.js 官方示例

express-example/
├── bin/                      # 启动脚本
├── public/                   # 静态资源
├── routes/                   # 路由
├── views/                    # 视图模板
├── app.js                    # 应用配置
└── package.json

特点:简单直接,适合小型项目。

5.2 NestJS(企业级 Node.js 框架)

nestjs-project/
├── src/
│   ├── modules/              # 功能模块
│   │   ├── users/
│   │   │   ├── users.controller.ts
│   │   │   ├── users.service.ts
│   │   │   ├── users.module.ts
│   │   │   └── dto/
│   │   └── orders/
│   ├── common/               # 共享模块
│   ├── config/               # 配置
│   └── main.ts               # 入口

特点

  • 强制模块化结构
  • 内置依赖注入
  • 适合大型项目

5.3 DjangoPython

django-project/
├── project_name/             # 项目配置
├── apps/
│   ├── users/                # 用户应用
│   │   ├── models.py
│   │   ├── views.py
│   │   ├── serializers.py
│   │   └── urls.py
│   └── orders/               # 订单应用
├── templates/
├── static/
└── manage.py

特点

  • 约定优于配置
  • MTVModel-Template-View)模式
  • 应用可复用

5.4 Spring BootJava

spring-boot-project/
├── src/main/java/
│   └── com/example/
│       ├── controller/
│       ├── service/
│       ├── repository/
│       ├── entity/
│       ├── dto/
│       ├── config/
│       └── Application.java
├── src/main/resources/
│   ├── application.yml
│   └── mapper/
└── src/test/

特点

  • 严格的分层架构
  • 注解驱动开发
  • 强大的生态

6. 架构设计原则与检查清单

6.1 核心原则

原则 说明 实践建议
单一职责 一个模块只做一件事 Controller 只处理 HTTPService 只处理业务
依赖倒置 依赖抽象而非具体实现 使用接口/抽象类
开闭原则 对扩展开放,对修改关闭 新增功能不修改原有代码
DRY 不要重复自己 提取公共逻辑到 utils 或基类
KISS 保持简单 不要过度设计

6.2 检查清单

分层检查

  • Controller 是否只处理 HTTP 相关逻辑?
  • Service 是否包含核心业务逻辑?
  • Repository 是否只负责数据访问?
  • 层与层之间是否通过明确的接口交互?

代码质量

  • 是否有统一的错误处理机制?
  • 是否使用环境变量管理配置?
  • 是否有日志记录?
  • 是否编写了单元测试?

安全

  • 敏感配置是否放入环境变量?
  • 是否有输入验证?
  • 是否有认证和授权?
  • 密码是否加密存储?

7. 总结

::: tip 💡 核心思想 好的后端架构应该像一家组织良好的餐厅:

  • 分工明确:每个角色知道自己的职责
  • 流程清晰:数据像流水一样在各层之间传递
  • 易于扩展:新增功能不会破坏现有结构
  • 便于测试:各层可以独立测试

记住这几点

  1. 分层是手段,不是目的:不要为了分层而分层
  2. 按功能组织:中大型项目推荐 Feature-based
  3. 统一约定:命名、结构、错误处理保持一致
  4. 持续重构:定期审视架构,及时调整

最终目标:让代码像整理好的车间一样,想找什么立刻能找到,新功能容易添加,旧代码容易维护。 :::


参考资源