08-Java工程师的Python第八课-框架入门

Flask/Django vs Spring:Python Web开发快速上手

摘要:Java有Spring,Python有Flask和Django。本文对比三种框架的设计理念和入门路径。


写在前面

作为一个Java工程师,你一定对Spring Boot的"约定优于配置"印象深刻。Python的Web框架同样遵循这一理念,但实现方式不同。

Spring强调"全功能、企业级",Flask强调"微框架、灵活扩展",Django强调"全功能、敏捷开发"。


一、框架生态对比

1.1 Java的Spring帝国

scss 复制代码
Spring Boot
├── Spring MVC (Web层)
├── Spring Data (数据层)
├── Spring Security (安全)
├── Spring Cloud (微服务)
└── ... (无数子项目)

Spring Boot的核心优势:

  • 自动配置(Auto Configuration)
  • 起步依赖(Starter Dependencies)
  • 嵌入式服务器
  • 生产级特性(Actuator、Metrics)

1.2 Python的框架生态

bash 复制代码
Python Web框架
├── Django       # 全功能框架
│   ├── ORM
│   ├── Admin
│   ├── Templates
│   └── Auth
├── Flask        # 微框架
│   ├── 核心
│   └── 扩展(Flask-SQLAlchemy, Flask-Login等)
├── FastAPI     # 现代异步框架
│   ├── 自动文档
│   ├── 类型提示
│   └── 异步支持
└── Pyramid     # 介于两者之间

二、Flask:微框架的典范

2.1 核心概念对比

Spring Boot Flask
@RestController @app.route()
@RequestMapping app.route()
@PathVariable <variable_name>
@RequestParam request.args.get()
@RequestBody request.get_json()
返回对象/JSON return jsonify(data)

2.2 最小应用

java 复制代码
// Spring Boot
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
@RequestMapping("/api")
public class UserController {
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
}
python 复制代码
# Flask
from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route("/api/users/<int:id>")
def get_user(id):
    user = user_service.find_by_id(id)
    return jsonify(user)

if __name__ == "__main__":
    app.run(debug=True)

2.3 请求处理对比

java 复制代码
// Spring Boot - 完整示例
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    public User createUser(@RequestBody @Valid UserRequest request) {
        return userService.create(request);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id,
                          @RequestBody UserRequest request) {
        return userService.update(id, request);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }

    @GetMapping
    public List<User> listUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        return userService.findAll(page, size);
    }
}
python 复制代码
# Flask - 完整示例
from flask import Flask, jsonify, request
from flask.views import MethodView

app = Flask(__name__)

class UserView(MethodView):
    def get(self, user_id=None):
        if user_id is None:
            page = request.args.get("page", 0, type=int)
            size = request.args.get("size", 10, type=int)
            return jsonify(user_service.find_all(page, size))
        return jsonify(user_service.find_by_id(user_id))

    def post(self):
        data = request.get_json()
        return jsonify(user_service.create(data)), 201

    def put(self, user_id):
        data = request.get_json()
        return jsonify(user_service.update(user_id, data))

    def delete(self, user_id):
        user_service.delete(user_id)
        return "", 204

# 注册路由
app.add_url_rule("/api/users", view_func=UserView.as_view("users"))
app.add_url_rule("/api/users/<int:user_id>", view_func=UserView.as_view("user"))

三、Django:全功能框架

3.1 Django vs Spring Boot

概念 Django Spring Boot
项目结构 django-admin startproject spring initializr
应用 App Module/Component
ORM Django ORM JPA/Hibernate
路由 urls.py @RequestMapping
视图 FBV / Class-based Controller
模板 Django Template Thymeleaf/Freemarker
Admin 内置Admin站点 Spring Admin
配置 settings.py application.yml

3.2 Django项目结构

bash 复制代码
myproject/
├── manage.py              # Django CLI工具
├── myproject/
│   ├── __init__.py
│   ├── settings.py         # 配置文件
│   ├── urls.py             # 根路由
│   ├── wsgi.py             # WSGI入口
│   └── asgi.py             # ASGI入口
└── myapp/
    ├── __init__.py
    ├── models.py           # 数据模型
    ├── views.py            # 视图
    ├── urls.py             # 应用路由
    ├── admin.py            # Admin配置
    └── migrations/         # 数据库迁移

3.3 Django ORM vs JPA

java 复制代码
// Spring Data JPA
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(unique = true)
    private String email;

    private Integer age;

    @ManyToMany
    @JoinTable(name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;
}

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByAgeGreaterThan(int age);
    Optional<User> findByEmail(String email);
    @Query("SELECT u FROM User u WHERE u.name LIKE %:name%")
    List<User> searchByName(@Param("name") String name);
}
python 复制代码
# Django ORM
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    age = models.IntegerField(null=True, blank=True)
    roles = models.ManyToManyField("Role", through="UserRole")

    class Meta:
        db_table = "users"

    def __str__(self):
        return self.name

# 查询
User.objects.all()
User.objects.filter(age__gt=18)
User.objects.get(email="alice@example.com")
User.objects.filter(name__contains="Alice")

3.4 Django REST Framework

java 复制代码
// Spring Data REST + Jackson
@Entity
public class User {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private String email;
}

@RestRepositoryResource
public interface UserRepository extends JpaRepository<User, Long> {
}
python 复制代码
# Django REST Framework
from rest_framework import serializers, viewsets

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "name", "email"]

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

# 自动生成CRUD + 列表 + 分页 + 过滤 + 搜索
# API文档:http://localhost:8000/docs/

四、FastAPI:现代异步框架

4.1 概念对比

Spring FastAPI
@RestController @app.get/post/put/delete()
@RequestBody Pydantic Model
CompletableFuture async/await
@Async async def
Spring Doc (OpenAPI) 自动生成
WebFlux 原生异步

4.2 FastAPI示例

python 复制代码
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class User(BaseModel):
    name: str
    email: str
    age: Optional[int] = None

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

users_db = []

@app.post("/users", response_model=UserResponse)
async def create_user(user: User):
    new_user = UserResponse(
        id=len(users_db) + 1,
        name=user.name,
        email=user.email
    )
    users_db.append(new_user)
    return new_user

@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
    return users_db[user_id - 1]

@app.get("/users")
async def list_users(skip: int = 0, limit: int = 10):
    return users_db[skip:skip+limit]

FastAPI自动:

  • 生成OpenAPI文档:/docs(Swagger UI)或 /redoc
  • 验证请求数据(Pydantic)
  • 生成响应数据
  • 支持异步

五、中间件与拦截器

5.1 Java过滤器/拦截器

java 复制代码
// Spring Boot 过滤器
@Component
@Order(1)
public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request,
                        ServletResponse response,
                        FilterChain chain)
            throws IOException, ServletException {
        long start = System.currentTimeMillis();
        chain.doFilter(request, response);
        log.info("耗时: {}ms", System.currentTimeMillis() - start);
    }
}

// 拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) {
        String token = request.getHeader("Authorization");
        if (!isValid(token)) {
            response.setStatus(401);
            return false;
        }
        return true;
    }
}

5.2 Flask中间件

python 复制代码
# Flask 装饰器实现
from functools import wraps
import time

def log_request(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"耗时: {time.time() - start:.2f}ms")
        return result
    return wrapper

@app.route("/api/users")
@log_request
def get_users():
    return jsonify(users)

# Flask 中间件(WSGI级别)
def middleware(app):
    def logMiddleware(environ, start_response):
        # 请求前处理
        response = app(environ, start_response)
        # 响应后处理
        return response
    return logMiddleware

5.3 Django中间件

python 复制代码
# Django 中间件
class LoggingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        start = time.time()
        response = self.get_response(request)
        duration = time.time() - start
        print(f"请求 {request.path} 耗时 {duration:.2f}ms")
        return response

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.common.CommonMiddleware',
    'myapp.middleware.LoggingMiddleware',
]

六、依赖注入对比

6.1 Java Spring DI

java 复制代码
@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findById(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

@RestController
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
}

6.2 Flask依赖注入

python 复制代码
# Flask 手动DI
class UserService:
    def __init__(self, repository):
        self.repository = repository

    def find_by_id(self, user_id):
        return self.repository.find_by_id(user_id)

# 手动组装
user_repository = UserRepository()
user_service = UserService(user_repository)
user_controller = UserController(user_service)

# Flask-Injector(可选)
from flask_injector import FlaskInjector

FlaskInjector(app=app, modules=[UserModule])

6.3 FastAPI依赖注入

python 复制代码
# FastAPI 内置依赖注入
from fastapi import Depends

def get_user_repository():
    return UserRepository()

@app.post("/users")
async def create_user(
    user: User,
    repo: UserRepository = Depends(get_user_repository)
):
    return repo.create(user)

# 带缓存的依赖
from functools import lru_cache

@lru_cache()
def get_settings():
    return Settings()

七、错误处理对比

7.1 Spring全局异常

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    public Result handleBusiness(BusinessException e) {
        return Result.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidation(MethodArgumentNotValidException e) {
        String msg = e.getBindingResult().getFieldErrors()
            .stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(", "));
        return Result.error("VALIDATION_ERROR", msg);
    }
}

7.2 Flask错误处理

python 复制代码
from flask import jsonify

@app.errorhandler(BusinessException)
def handle_business(e):
    return jsonify({"code": e.code, "message": e.message}), 400

@app.errorhandler(ValidationError)
def handle_validation(e):
    return jsonify({"code": "VALIDATION_ERROR", "message": str(e)}), 400

@app.errorhandler(404)
def not_found(e):
    return jsonify({"code": "NOT_FOUND", "message": "资源不存在"}), 404

# FastAPI 更简洁
from fastapi import HTTPException

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    user = find_user(user_id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user

八、测试对比

8.1 Spring Boot测试

java 复制代码
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    public void testGetUser() throws Exception {
        when(userService.findById(1L))
            .thenReturn(new User("Alice", "alice@example.com"));

        mockMvc.perform(get("/api/users/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("Alice"))
            .andExpect(jsonPath("$.email").value("alice@example.com"));
    }
}

8.2 Flask测试

python 复制代码
import pytest
from flask import Flask

@pytest.fixture
def app():
    app = Flask(__name__)
    app.config["TESTING"] = True

    @app.route("/users/<int:user_id>")
    def get_user(user_id):
        user = user_service.find_by_id(user_id)
        return jsonify(user)

    return app

@pytest.fixture
def client(app):
    return app.test_client()

def test_get_user(monkeypatch):
    def mock_find_by_id(user_id):
        return {"id": user_id, "name": "Alice", "email": "alice@example.com"}

    monkeypatch.setattr(user_service, "find_by_id", mock_find_by_id)

    response = client.get("/users/1")
    assert response.status_code == 200
    assert response.json["name"] == "Alice"

九、项目结构最佳实践

9.1 Java vs Python项目结构对比

java 复制代码
// Java Spring Boot 标准结构
my-spring-project/
├── pom.xml                          # Maven配置
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java    # 启动类
│   │   │       ├── controller/             # 控制器
│   │   │       ├── service/                # 服务层
│   │   │       ├── repository/             # 数据访问
│   │   │       ├── entity/                 # 实体类
│   │   │       ├── dto/                    # 数据传输对象
│   │   │       ├── config/                 # 配置类
│   │   │       └── exception/              # 异常处理
│   │   └── resources/
│   │       ├── application.yml             # 配置文件
│   │       └── static/                     # 静态资源
│   └── test/
│       └── java/
└── README.md
python 复制代码
# Python FastAPI 标准结构(推荐)
my-fastapi-project/
├── pyproject.toml                   # 项目配置(现代标准)
├── requirements.txt                 # 依赖列表(兼容)
├── README.md
├── .env.example                     # 环境变量示例
├── .gitignore
├── src/                             # 源代码目录
│   └── myapp/
│       ├── __init__.py
│       ├── main.py                  # 入口文件
│       ├── core/                    # 核心配置
│       │   ├── __init__.py
│       │   ├── config.py            # 配置管理
│       │   ├── security.py          # 安全相关
│       │   └── dependencies.py      # 依赖注入
│       ├── api/                     # API层
│       │   ├── __init__.py
│       │   ├── deps.py              # API依赖
│       │   └── v1/                  # API版本
│       │       ├── __init__.py
│       │       ├── endpoints/
│       │       │   ├── __init__.py
│       │       │   ├── users.py
│       │       │   └── auth.py
│       │       └── router.py
│       ├── models/                  # 数据模型
│       │   ├── __init__.py
│       │   └── user.py
│       ├── schemas/                 # Pydantic模型
│       │   ├── __init__.py
│       │   └── user.py
│       ├── services/                # 业务逻辑
│       │   ├── __init__.py
│       │   └── user_service.py
│       ├── repositories/            # 数据访问
│       │   ├── __init__.py
│       │   └── user_repo.py
│       └── utils/                   # 工具函数
│           ├── __init__.py
│           └── helpers.py
├── tests/                           # 测试目录
│   ├── __init__.py
│   ├── conftest.py                  # pytest配置
│   └── test_users.py
└── alembic/                         # 数据库迁移
    └── versions/

9.2 三种框架的项目结构对比

Flask 项目结构
python 复制代码
# Flask 小型项目
flask-app/
├── app.py                    # 单文件应用(适合小型项目)
├── requirements.txt
└── templates/
    └── index.html

# Flask 中大型项目(推荐)
flask-app/
├── wsgi.py                   # WSGI入口
├── app/
│   ├── __init__.py           # 创建Flask应用
│   ├── extensions.py         # 扩展初始化
│   ├── config.py             # 配置
│   ├── models/
│   │   ├── __init__.py
│   │   └── user.py
│   ├── routes/
│   │   ├── __init__.py
│   │   └── user_routes.py
│   ├── services/
│   │   └── user_service.py
│   ├── templates/
│   └── static/
├── migrations/
├── tests/
└── requirements.txt
Django 项目结构
python 复制代码
# Django 项目结构
django-project/
├── manage.py
├── config/                   # 项目配置
│   ├── __init__.py
│   ├── settings/
│   │   ├── __init__.py
│   │   ├── base.py          # 基础配置
│   │   ├── development.py   # 开发环境
│   │   └── production.py    # 生产环境
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── apps/                     # 应用目录
│   ├── users/               # 用户应用
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── views.py
│   │   ├── urls.py
│   │   ├── serializers.py   # DRF序列化器
│   │   ├── services.py      # 业务逻辑
│   │   └── migrations/
│   └── orders/              # 订单应用
│       └── ...
├── templates/
├── static/
├── media/
├── tests/
└── requirements.txt
FastAPI 项目结构
python 复制代码
# FastAPI 项目结构(推荐)
fastapi-project/
├── pyproject.toml            # 项目配置
├── src/
│   └── app/
│       ├── __init__.py
│       ├── main.py           # FastAPI应用入口
│       ├── api/
│       │   ├── __init__.py
│       │   ├── deps.py       # 公共依赖
│       │   └── v1/
│       │       ├── __init__.py
│       │       ├── router.py # 汇总路由
│       │       └── endpoints/
│       │           ├── users.py
│       │           └── items.py
│       ├── core/
│       │   ├── __init__.py
│       │   ├── config.py     # 配置
│       │   └── security.py   # JWT等
│       ├── models/           # SQLAlchemy模型
│       │   ├── __init__.py
│       │   └── user.py
│       ├── schemas/          # Pydantic模型
│       │   ├── __init__.py
│       │   └── user.py
│       ├── crud/             # CRUD操作
│       │   ├── __init__.py
│       │   └── user.py
│       └── db/
│           ├── __init__.py
│           ├── base.py       # Base类
│           └── session.py    # 数据库会话
├── tests/
├── alembic/
└── docker-compose.yml

9.3 目录规范详解

命名规范对比
类型 Java Python
包名/模块名 com.example.userService user_service
类名 UserService UserService
函数名 getUserById get_user_by_id
变量名 userName user_name
常量 MAX_SIZE MAX_SIZE
文件名 UserService.java user_service.py
__init__.py 的作用
python 复制代码
# Python的__init__.py文件
# 1. 标识目录为Python包
# 2. 可以导出公共接口
# 3. 可以执行初始化代码

# myapp/__init__.py
from .main import create_app
from .models import User
from .services import UserService

__all__ = ["create_app", "User", "UserService"]

# 使用时可以直接导入
from myapp import User, UserService
配置管理对比
java 复制代码
// Java - application.yml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
python 复制代码
# Python - 使用pydantic-settings(推荐)
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "My API"
    database_url: str
    secret_key: str
    debug: bool = False

    class Config:
        env_file = ".env"

settings = Settings()

# 使用
from app.core.config import settings
print(settings.database_url)

9.4 分层架构对比

java 复制代码
// Java Spring Boot 分层
Controller → Service → Repository → Entity

// 典型调用链
UserController
    ↓
UserService (业务逻辑)
    ↓
UserRepository (数据访问)
    ↓
User (实体)
python 复制代码
# Python FastAPI 分层(推荐)
Router → Service → Repository → Model

# 典型调用链
users.py (endpoints)
    ↓
user_service.py (业务逻辑)
    ↓
user_repo.py (数据访问)
    ↓
user.py (SQLAlchemy Model)

# schemas/ 用于请求/响应的数据验证

9.5 项目配置文件对比

java 复制代码
// Java - pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
python 复制代码
# Python - pyproject.toml(现代标准)
[project]
name = "my-api"
version = "1.0.0"
description = "My FastAPI Project"
requires-python = ">=3.10"
dependencies = [
    "fastapi>=0.100.0",
    "uvicorn>=0.23.0",
    "sqlalchemy>=2.0.0",
    "pydantic>=2.0.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "black>=23.0.0",
    "mypy>=1.0.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

9.6 最佳实践建议

实践 Java Python
配置管理 application.yml + @Value pydantic-settings + .env
依赖注入 Spring IoC容器 FastAPI Depends()
数据验证 @Valid + Bean Validation Pydantic自动验证
日志 SLF4J + Logback logging模块
测试 JUnit + Mockito pytest + pytest-asyncio
代码风格 Checkstyle/Spotless Black + Ruff
类型检查 编译时检查 mypy静态检查

十、总结与选择建议

场景 推荐框架 理由
微服务/API Spring Boot + FastAPI Spring生态 + 异步性能
快速原型 Django 全功能、内置Admin
小型API Flask 轻量、灵活
高性能异步 FastAPI async/await、自动文档
学习Web开发 Flask 概念简单、代码少

Java工程师的选择建议

  • 如果你做企业级开发 → Django(类Spring的全功能框架)
  • 如果你要快速构建REST API → FastAPI(现代、类型安全)
  • 如果你做微服务 → Spring Cloud + FastAPI混合

Python Web框架的设计理念是"选择优于约定"。Django给你全部功能,Flask给你基础让你选择,FastAPI给你类型安全。三者各有优势,根据项目需求选择。

相关推荐
lancyu40 分钟前
关于多轮对话机器人的上下文Token优化和解决方案
人工智能·python·深度学习·机器学习·chatgpt·机器人·prompt
草莓橙子碗1 小时前
Claude 使用指南
开发语言·python
工具分享1 小时前
陪跑跟品爆单AI选品助手,高效跟品会赔本吗?
人工智能·python
COOLMO研究AI2 小时前
Python 如何实现 AI API 的提示词(Prompt)版本管理与热更新
人工智能·python·prompt
老郑聊AI业财智造2 小时前
Transformer 技术架构与源码分析
人工智能·python·深度学习·语言模型·架构·transformer·软件工程
程序员三藏2 小时前
自动化测试用例编写详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
230万光年的思念2 小时前
分子动力学模拟参考文献
python
HongXu_CaiYi3 小时前
0103-python相关-函数、文件
python
vortex54 小时前
从Conda到UV:Python项目依赖管理的现代演进
python·conda·uv
何以解忧,唯有..4 小时前
Python time 模块详解:时间处理与日期操作指南
开发语言·python