企业应用框架速成:鸡翅 7 天实战,从 0 基础到独立搭建
你是否曾写过一个“能跑就行”的 Flask 脚本,却在项目变大后陷入混乱?变量满天飞、逻辑耦合严重、改一处崩三处?
《企业应用框架速成:鸡翅 7 天实战》正是为解决这一痛点而生。它不堆砌理论,而是用 7 天时间,带你从零构建一个具备配置管理、分层架构、依赖注入、统一异常处理和中间件机制的轻量级企业应用框架。
本文将浓缩课程精华,配合真实可运行的 Python 代码,手把手演示如何一步步搭建这个框架。
🗓 第 1 天:项目初始化与配置中心
告别 app.py 单文件!我们先建立标准工程结构:
bash
编辑
enterprise-app/
├── config/
│ └── settings.py # 配置管理
├── core/
│ └── app_factory.py # 应用工厂
├── api/
│ └── v1/
│ └── user.py # API 路由
├── services/
│ └── user_service.py # 业务逻辑
├── repositories/
│ └── user_repo.py # 数据访问
├── middleware/
│ └── logger.py # 中间件
├── main.py # 入口文件
└── requirements.txt
config/settings.py —— 环境驱动配置:
python
编辑
import os
class Config:
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
DATABASE_URL = os.getenv("DB_URL", "sqlite:///./app.db")
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-2025")
config = Config()
✅ 优势:通过
export DEBUG=true切换环境,无需改代码。
🗓 第 2 天:应用工厂 + 依赖注入容器
core/app_factory.py:
python
编辑
from flask import Flask
from config.settings import config
# 简易依赖注入容器
class DIContainer:
_services = {}
@classmethod
def register(cls, name, instance):
cls._services[name] = instance
@classmethod
def get(cls, name):
return cls._services[name]
def create_app():
app = Flask(__name__)
app.config.from_object(config)
# 注册服务(实际项目中可自动扫描)
from repositories.user_repo import InMemoryUserRepository
from services.user_service import UserService
repo = InMemoryUserRepository()
service = UserService(repo)
DIContainer.register("user_service", service)
# 注册蓝图
from api.v1.user import bp as user_bp
app.register_blueprint(user_bp, url_prefix="/api/v1")
return app
🔑 核心思想:解耦!Service 不直接 new Repo,而是由容器提供。
🗓 第 3 天:三层架构落地(Controller → Service → Repository)
api/v1/user.py(Controller 层) :
python
编辑
from flask import Blueprint, request, jsonify
from core.app_factory import DIContainer
bp = Blueprint("user", __name__)
@bp.route("/users", methods=["POST"])
def create_user():
data = request.get_json()
service = DIContainer.get("user_service")
try:
user = service.create(data["name"], data["email"])
return jsonify(user), 201
except ValueError as e:
return jsonify({"error": str(e)}), 400
services/user_service.py(Service 层) :
python
编辑
class UserService:
def __init__(self, user_repo):
self.repo = user_repo
def create(self, name, email):
if "@" not in email:
raise ValueError("Invalid email format")
return self.repo.save({"name": name, "email": email})
repositories/user_repo.py(Repository 层) :
python
编辑
class InMemoryUserRepository:
def __init__(self):
self._db = []
self._id_counter = 1
def save(self, user_data):
user_data["id"] = self._id_counter
self._id_counter += 1
self._db.append(user_data)
return user_data
🧱 架构价值:
- 修改数据库?只需重写
UserRepository- 新增业务规则?只动
UserService- 换 API 框架?Controller 层隔离变化
🗓 第 4 天:统一异常处理与日志
在 create_app() 中添加全局错误处理器:
python
编辑
@app.errorhandler(Exception)
def handle_unexpected_error(e):
app.logger.error(f"Unexpected error: {str(e)}")
return jsonify({"error": "Internal server error"}), 500
@app.errorhandler(ValueError)
def handle_business_error(e):
return jsonify({"error": str(e)}), 400
同时集成结构化日志:
python
编辑
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s'
)
🗓 第 5 天:中间件 —— 请求日志与耗时统计
middleware/logger.py:
python
编辑
from flask import request, g
import time
def setup_middleware(app):
@app.before_request
def start_timer():
g.start_time = time.time()
@app.after_request
def log_request(response):
duration = time.time() - g.start_time
app.logger.info(
f"{request.method} {request.path} -> {response.status_code} "
f"({duration:.3f}s)"
)
return response
在 create_app() 中启用:
python
编辑
from middleware.logger import setup_middleware
setup_middleware(app)
🗓 第 6 天:数据库抽象(切换到 SQLAlchemy)
将 InMemoryUserRepository 替换为 ORM 版本:
python
编辑
# core/database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# models/user.py
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
Service 层几乎无需改动,仅需调整 Repository 的实现方式。
🗓 第 7 天:测试 + 部署脚本
tests/test_user_api.py:
python
编辑
import pytest
from main import app
@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_create_user_success(client):
resp = client.post("/api/v1/users", json={"name": "Alice", "email": "alice@example.com"})
assert resp.status_code == 201
assert resp.json["name"] == "Alice"
Dockerfile 实现一键部署:
dockerfile
编辑
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "-k", "gevent", "--bind", "0.0.0.0:8000", "main:app"]
为什么这套框架值得掌握?
- 快速启动新项目:7 天后,你拥有自己的脚手架;
- 面试加分项:展示工程化思维,远超“会调 API”;
- 团队协作基础:清晰分层让多人开发不打架;
- 平滑演进:从小型工具到百万级系统,架构可扩展