【FastAPI】FastAPI RESTful API实战:从接口规范到优雅设计

FastAPI RESTful API实战:从接口规范到优雅设计

前言

这篇是 Python 基础合集的学习笔记,这次整理的是 RESTful API 的设计规范和 FastAPI 实战。

说到这个话题,其实有点小故事。前阵子刚进一家公司实习,第一周就被前端同事"教育"了一顿。为啥?因为我写的接口太乱了------查询用户用 POST,删除订单用 GET,返回的数据格式也是五花八门......前端同事看着我的接口文档,一脸无奈地问:"你这接口,我怎么调?"

后来导师告诉我,团队里大家都遵循 RESTful 规范,让我赶紧补课。你想想,一个团队十几个后端,如果每个人接口风格都不一样,前端不得疯掉?所以 RESTful 不只是个技术规范,更是团队协作的"共同语言"。

本篇会从 RESTful 的核心概念讲起,然后用 FastAPI 一步步实现规范的接口,最后还有完整的实战案例。看完这篇,你也能写出让前端同事"刮目相看"的接口了。

🏠个人主页:山沐与山


文章目录

  • [一、RESTful API是什么](#一、RESTful API是什么)
    • [1.1 一个"被揍"的故事](#1.1 一个"被揍"的故事)
    • [1.2 REST的四个关键词](#1.2 REST的四个关键词)
    • [1.3 RESTful API长什么样](#1.3 RESTful API长什么样)
  • 二、RESTful设计规范详解
    • [2.1 URI设计:用名词不用动词](#2.1 URI设计:用名词不用动词)
    • [2.2 HTTP方法:增删改查的正确姿势](#2.2 HTTP方法:增删改查的正确姿势)
    • [2.3 状态码:让响应会"说话"](#2.3 状态码:让响应会"说话")
    • [2.4 查询参数:分页、过滤、排序](#2.4 查询参数:分页、过滤、排序)
    • [2.5 版本控制:新老接口兼容](#2.5 版本控制:新老接口兼容)
  • [三、FastAPI实现RESTful API](#三、FastAPI实现RESTful API)
    • [3.1 项目初始化](#3.1 项目初始化)
    • [3.2 定义数据模型](#3.2 定义数据模型)
    • [3.3 实现CRUD接口](#3.3 实现CRUD接口)
    • [3.4 统一响应格式](#3.4 统一响应格式)
  • 四、进阶技巧
    • [4.1 嵌套资源](#4.1 嵌套资源)
    • [4.2 非CRUD操作怎么办](#4.2 非CRUD操作怎么办)
    • [4.3 错误处理](#4.3 错误处理)
    • [4.4 自动生成API文档](#4.4 自动生成API文档)
  • 五、完整实战案例:用户管理系统
  • 六、常见问题
  • 七、总结

一、RESTful API是什么

1.1 一个"被揍"的故事

假设你是刚入职的后端程序员小阿八,负责给前端的阿花提供 API 接口。你兴冲冲地写了一周代码,结果被阿花揍得鼻青脸肿:

复制代码
你写的接口:
GET  /getUserList          获取用户列表
POST /deleteUser?id=123    删除用户
GET  /updateUserName       修改用户名
POST /addNewUser           新增用户

阿花看了直摇头:"你这接口风格太乱了,我调用都得猜半天!"

你一脸委屈:接口不是能跑就行吗?

不行!这就是为什么要学 RESTful API

1.2 REST的四个关键词

REST 全称是 Representational State Transfer,翻译过来叫"表现层状态转移"。听起来很抽象?别急,我拆开来讲:

R - Representational(表现层)

资源可以有不同的"表现形式"。比如同一个用户数据,可以用 JSON 格式返回,也可以用 XML 格式返回。目前 JSON 是主流。

json 复制代码
// JSON 格式(推荐)
{"id": 1, "name": "张三", "email": "zhangsan@example.com"}
xml 复制代码
<!-- XML 格式(较少使用) -->
<user>
  <id>1</id>
  <name>张三</name>
  <email>zhangsan@example.com</email>
</user>

S - State(状态)

这里说的是"无状态"。什么意思呢?

  • 有状态:你去餐厅吃饭,服务员记得你上次点了鱼皮,这次直接问"还是老样子?"
  • 无状态:服务员不记得你是谁,每次都要重新点单

RESTful API 是无状态的------服务器不记录客户端的任何信息,每次请求都是独立的。这样做的好处是:想加多少台服务器都行,任何一台都能处理请求,轻松实现负载均衡。

T - Transfer(转移)

转移是双向的:

  • GET 请求:服务器把资源状态"转移"给客户端
  • POST 请求:客户端把新的状态"转移"给服务器

组合起来

REST 是一种软件架构风格,让客户端和服务器通过统一的接口,以无状态的方式互相传递资源的表现层数据。

RESTful 就是"充满 REST 风格的",RESTful API 就是符合 REST 架构风格的 API

注意:RESTful 不是协议,不是标准,不是强制规范,只是一种建议的设计风格。你可以遵循,也可以不遵循。

1.3 RESTful API长什么样

还是用户管理的例子,对比一下:

操作 不规范的写法 RESTful写法
获取用户列表 GET /getUserList GET /users
获取单个用户 GET /getUserById?id=1 GET /users/1
创建用户 POST /addUser POST /users
更新用户 POST /updateUser PUT /users/1
删除用户 GET /deleteUser?id=1 DELETE /users/1

看到没?RESTful 风格的接口:

  • URI名词users),不用动词(getUser
  • HTTP 方法 表示操作(GET/POST/PUT/DELETE
  • 结构清晰,一眼就能看懂

二、RESTful设计规范详解

2.1 URI设计:用名词不用动词

这是 RESTful 最核心的原则之一。

资源用名词复数

复制代码
✅ /users          用户列表
✅ /products       商品列表
✅ /orders         订单列表

❌ /getUsers       动词,不推荐
❌ /user           单数,不推荐(除非确实只有一个)

具体资源加ID

复制代码
✅ /users/123              ID为123的用户
✅ /products/456           ID为456的商品
✅ /orders/789             ID为789的订单

嵌套资源

复制代码
✅ /users/123/orders       用户123的所有订单
✅ /orders/789/items       订单789的所有商品项

⚠️ 不建议嵌套太深:
❌ /users/123/orders/789/items/1/reviews    太深了!

2.2 HTTP方法:增删改查的正确姿势

方法 用途 是否幂等 示例
GET 查询资源 GET /users 获取用户列表
POST 创建资源 POST /users 创建新用户
PUT 完整更新资源 PUT /users/1 更新用户1的全部信息
PATCH 部分更新资源 PATCH /users/1 只更新用户1的某些字段
DELETE 删除资源 DELETE /users/1 删除用户1

什么是幂等?

幂等就是:同样的请求执行一次和执行多次,效果一样。

  • GET /users/1:查10次,结果都一样------幂等
  • DELETE /users/1:删第一次成功,再删就404了,但用户1确实没了------幂等
  • POST /users:每次都会创建一个新用户------不幂等

2.3 状态码:让响应会"说话"

HTTP 状态码分为5类,常用的需要记住:

状态码 含义 使用场景
200 OK 请求成功(通用)
201 Created 创建资源成功
204 No Content 删除成功,无返回内容
400 Bad Request 客户端请求参数错误
401 Unauthorized 未认证(没登录)
403 Forbidden 已认证但无权限
404 Not Found 资源不存在
422 Unprocessable Entity 参数格式正确但语义错误
500 Internal Server Error 服务器内部错误

前端看到 4xx 就知道是自己参数传错了,看到 5xx 就知道是后端的锅------谁也别想甩锅!

2.4 查询参数:分页、过滤、排序

复杂查询用查询参数(Query Parameters)实现:

分页

复制代码
GET /users?page=1&size=10
GET /users?offset=0&limit=10

过滤

复制代码
GET /users?status=active
GET /users?role=admin&status=active
GET /products?price_min=100&price_max=500

排序

复制代码
GET /users?sort=created_at
GET /users?sort=-created_at          # 降序(加减号)
GET /users?sort=name,-created_at     # 多字段排序

搜索

复制代码
GET /users?q=张三
GET /products?keyword=手机

2.5 版本控制:新老接口兼容

接口升级时,为了不影响老用户,可以在 URI 中加版本号:

复制代码
GET /v1/users     # 老版本
GET /v2/users     # 新版本

或者放在 Header 里:

复制代码
GET /users
Accept: application/vnd.myapi.v1+json

推荐用 URI 方式,更直观。


三、FastAPI实现RESTful API

3.1 项目初始化

先安装依赖:

bash 复制代码
pip install fastapi uvicorn pydantic

创建项目结构:

复制代码
restful_demo/
├── main.py              # 入口文件
├── models.py            # 数据模型
├── schemas.py           # Pydantic 模型
├── database.py          # 模拟数据库
└── routers/
    └── users.py         # 用户相关路由

3.2 定义数据模型

schemas.py

python 复制代码
from pydantic import BaseModel, EmailStr, Field
from typing import Optional
from datetime import datetime


class UserBase(BaseModel):
    """用户基础模型"""
    name: str = Field(..., min_length=2, max_length=50, description="用户名")
    email: EmailStr = Field(..., description="邮箱")
    age: Optional[int] = Field(None, ge=0, le=150, description="年龄")


class UserCreate(UserBase):
    """创建用户的请求模型"""
    password: str = Field(..., min_length=6, description="密码")


class UserUpdate(BaseModel):
    """更新用户的请求模型(所有字段可选)"""
    name: Optional[str] = Field(None, min_length=2, max_length=50)
    email: Optional[EmailStr] = None
    age: Optional[int] = Field(None, ge=0, le=150)


class UserResponse(UserBase):
    """用户响应模型"""
    id: int
    is_active: bool = True
    created_at: datetime

    class Config:
        from_attributes = True


class PaginatedResponse(BaseModel):
    """分页响应模型"""
    total: int = Field(..., description="总数量")
    page: int = Field(..., description="当前页码")
    size: int = Field(..., description="每页数量")
    items: list = Field(..., description="数据列表")

3.3 实现CRUD接口

database.py(模拟数据库):

python 复制代码
from datetime import datetime
from typing import Dict, Optional

# 模拟数据库
USERS_DB: Dict[int, dict] = {
    1: {
        "id": 1,
        "name": "张三",
        "email": "zhangsan@example.com",
        "age": 25,
        "password": "hashed_password_1",
        "is_active": True,
        "created_at": datetime(2024, 1, 1, 10, 0, 0)
    },
    2: {
        "id": 2,
        "name": "李四",
        "email": "lisi@example.com",
        "age": 30,
        "password": "hashed_password_2",
        "is_active": True,
        "created_at": datetime(2024, 1, 15, 14, 30, 0)
    }
}

# 自增ID
_next_id = 3


def get_next_id() -> int:
    global _next_id
    current = _next_id
    _next_id += 1
    return current

routers/users.py

python 复制代码
from fastapi import APIRouter, HTTPException, Query, Path, status
from typing import Optional, List
from datetime import datetime

from schemas import UserCreate, UserUpdate, UserResponse, PaginatedResponse
from database import USERS_DB, get_next_id

router = APIRouter(prefix="/v1/users", tags=["用户管理"])


# ============================================
# GET /users - 获取用户列表
# ============================================
@router.get("", response_model=PaginatedResponse, summary="获取用户列表")
async def get_users(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(10, ge=1, le=100, description="每页数量"),
    name: Optional[str] = Query(None, description="按用户名筛选"),
    is_active: Optional[bool] = Query(None, description="按状态筛选"),
    sort: Optional[str] = Query(None, description="排序字段,如 name, -created_at")
):
    """
    获取用户列表,支持分页、筛选、排序

    - **page**: 页码,从1开始
    - **size**: 每页数量,默认10,最大100
    - **name**: 按用户名模糊搜索
    - **is_active**: 按激活状态筛选
    - **sort**: 排序,字段前加-表示降序
    """
    # 筛选
    users = list(USERS_DB.values())

    if name:
        users = [u for u in users if name.lower() in u["name"].lower()]

    if is_active is not None:
        users = [u for u in users if u["is_active"] == is_active]

    # 排序
    if sort:
        desc = sort.startswith("-")
        field = sort.lstrip("-")
        if field in ["name", "created_at", "age"]:
            users.sort(key=lambda x: x.get(field, ""), reverse=desc)

    # 分页
    total = len(users)
    start = (page - 1) * size
    end = start + size
    paginated_users = users[start:end]

    return {
        "total": total,
        "page": page,
        "size": size,
        "items": paginated_users
    }


# ============================================
# GET /users/{user_id} - 获取单个用户
# ============================================
@router.get("/{user_id}", response_model=UserResponse, summary="获取用户详情")
async def get_user(
    user_id: int = Path(..., ge=1, description="用户ID")
):
    """根据ID获取用户详情"""
    if user_id not in USERS_DB:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 {user_id} 不存在"
        )
    return USERS_DB[user_id]


# ============================================
# POST /users - 创建用户
# ============================================
@router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED, summary="创建用户")
async def create_user(user: UserCreate):
    """
    创建新用户

    - 邮箱不能重复
    - 密码会被加密存储(这里简化处理)
    """
    # 检查邮箱是否已存在
    for existing_user in USERS_DB.values():
        if existing_user["email"] == user.email:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="邮箱已被注册"
            )

    # 创建用户
    user_id = get_next_id()
    new_user = {
        "id": user_id,
        "name": user.name,
        "email": user.email,
        "age": user.age,
        "password": f"hashed_{user.password}",  # 实际应该用 bcrypt 加密
        "is_active": True,
        "created_at": datetime.now()
    }

    USERS_DB[user_id] = new_user
    print(f"[+] 用户创建成功: {user.name} (ID: {user_id})")

    return new_user


# ============================================
# PUT /users/{user_id} - 完整更新用户
# ============================================
@router.put("/{user_id}", response_model=UserResponse, summary="完整更新用户")
async def update_user(
    user_id: int = Path(..., ge=1),
    user: UserCreate = ...
):
    """完整更新用户信息(需要传所有字段)"""
    if user_id not in USERS_DB:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 {user_id} 不存在"
        )

    existing = USERS_DB[user_id]
    existing.update({
        "name": user.name,
        "email": user.email,
        "age": user.age,
        "password": f"hashed_{user.password}"
    })

    print(f"[UPDATE] 用户 {user_id} 已更新")
    return existing


# ============================================
# PATCH /users/{user_id} - 部分更新用户
# ============================================
@router.patch("/{user_id}", response_model=UserResponse, summary="部分更新用户")
async def partial_update_user(
    user_id: int = Path(..., ge=1),
    user: UserUpdate = ...
):
    """部分更新用户信息(只传需要更新的字段)"""
    if user_id not in USERS_DB:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 {user_id} 不存在"
        )

    existing = USERS_DB[user_id]
    update_data = user.model_dump(exclude_unset=True)

    for field, value in update_data.items():
        if value is not None:
            existing[field] = value

    print(f"[PATCH] 用户 {user_id} 部分更新: {list(update_data.keys())}")
    return existing


# ============================================
# DELETE /users/{user_id} - 删除用户
# ============================================
@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT, summary="删除用户")
async def delete_user(
    user_id: int = Path(..., ge=1)
):
    """删除用户"""
    if user_id not in USERS_DB:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"用户 {user_id} 不存在"
        )

    deleted = USERS_DB.pop(user_id)
    print(f"[x] 用户已删除: {deleted['name']} (ID: {user_id})")

    # 204 No Content 不返回任何内容
    return None

3.4 统一响应格式

虽然 RESTful 没有强制要求响应格式,但团队统一格式是个好习惯:

python 复制代码
# schemas.py 添加

from typing import TypeVar, Generic
from pydantic import BaseModel

T = TypeVar("T")


class ApiResponse(BaseModel, Generic[T]):
    """统一响应格式"""
    code: int = 200
    message: str = "success"
    data: Optional[T] = None


class ErrorResponse(BaseModel):
    """错误响应格式"""
    code: int
    message: str
    detail: Optional[str] = None

使用示例:

python 复制代码
from schemas import ApiResponse, UserResponse

@router.get("/{user_id}", response_model=ApiResponse[UserResponse])
async def get_user(user_id: int):
    user = USERS_DB.get(user_id)
    if not user:
        return ApiResponse(code=404, message="用户不存在", data=None)
    return ApiResponse(data=user)

四、进阶技巧

4.1 嵌套资源

用户的订单、文章的评论,这些都是嵌套资源:

python 复制代码
# routers/orders.py

router = APIRouter(prefix="/v1", tags=["订单管理"])

# 获取用户的所有订单
@router.get("/users/{user_id}/orders", summary="获取用户订单列表")
async def get_user_orders(
    user_id: int = Path(..., ge=1),
    page: int = Query(1, ge=1),
    size: int = Query(10, ge=1, le=50)
):
    """获取指定用户的所有订单"""
    # 先检查用户是否存在
    if user_id not in USERS_DB:
        raise HTTPException(status_code=404, detail="用户不存在")

    # 查询该用户的订单
    user_orders = [o for o in ORDERS_DB.values() if o["user_id"] == user_id]

    # 分页处理...
    return {"total": len(user_orders), "items": user_orders}


# 获取用户的单个订单
@router.get("/users/{user_id}/orders/{order_id}", summary="获取订单详情")
async def get_user_order(
    user_id: int = Path(..., ge=1),
    order_id: int = Path(..., ge=1)
):
    """获取用户的某个订单详情"""
    order = ORDERS_DB.get(order_id)

    if not order or order["user_id"] != user_id:
        raise HTTPException(status_code=404, detail="订单不存在")

    return order

4.2 非CRUD操作怎么办

有些操作不是标准的增删改查,比如"支付订单"、"激活用户"。怎么设计?

方法一:用动词(不太RESTful,但直观)

复制代码
POST /orders/123/pay
POST /users/456/activate

方法二:把动作转换成名词(更RESTful)

复制代码
POST /orders/123/payments     # 创建一条支付记录
POST /users/456/activations   # 创建一条激活记录

方法三:用 PATCH 修改状态

复制代码
PATCH /orders/123
Body: {"status": "paid"}

PATCH /users/456
Body: {"is_active": true}

哪种都行,团队统一就好。我个人比较喜欢第三种,用 PATCH 修改状态。

4.3 错误处理

统一的错误处理让 API 更专业:

python 复制代码
# main.py

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError

app = FastAPI(title="RESTful API Demo", version="1.0.0")


# 自定义异常
class BusinessException(Exception):
    def __init__(self, code: int, message: str):
        self.code = code
        self.message = message


# 处理业务异常
@app.exception_handler(BusinessException)
async def business_exception_handler(request: Request, exc: BusinessException):
    return JSONResponse(
        status_code=exc.code,
        content={
            "code": exc.code,
            "message": exc.message,
            "path": str(request.url)
        }
    )


# 处理参数验证异常
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    errors = []
    for error in exc.errors():
        errors.append({
            "field": ".".join(str(x) for x in error["loc"]),
            "message": error["msg"]
        })

    return JSONResponse(
        status_code=422,
        content={
            "code": 422,
            "message": "参数验证失败",
            "errors": errors
        }
    )


# 处理 404
@app.exception_handler(404)
async def not_found_handler(request: Request, exc):
    return JSONResponse(
        status_code=404,
        content={
            "code": 404,
            "message": "资源不存在",
            "path": str(request.url)
        }
    )

4.4 自动生成API文档

FastAPI 自带 Swagger 文档,启动服务后访问:

  • Swagger UIhttp://localhost:8000/docs
  • ReDochttp://localhost:8000/redoc
  • OpenAPI JSONhttp://localhost:8000/openapi.json

前端拿着这个文档就能直接调用,还能在线测试,省去大量沟通成本。


五、完整实战案例:用户管理系统

把上面的代码整合起来,看完整示例:

main.py

python 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from routers import users

app = FastAPI(
    title="用户管理系统 API",
    description="一个符合 RESTful 规范的用户管理 API",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

# 跨域配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 注册路由
app.include_router(users.router)


# 健康检查
@app.get("/health", tags=["系统"])
async def health_check():
    return {"status": "ok"}


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

运行服务:

bash 复制代码
python main.py
# 或者
uvicorn main:app --reload

测试接口:

bash 复制代码
# 获取用户列表
curl http://localhost:8000/v1/users

# 获取单个用户
curl http://localhost:8000/v1/users/1

# 创建用户
curl -X POST http://localhost:8000/v1/users \
  -H "Content-Type: application/json" \
  -d '{"name": "王五", "email": "wangwu@example.com", "password": "123456"}'

# 部分更新
curl -X PATCH http://localhost:8000/v1/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name": "张三丰"}'

# 删除用户
curl -X DELETE http://localhost:8000/v1/users/1

# 分页 + 筛选 + 排序
curl "http://localhost:8000/v1/users?page=1&size=10&is_active=true&sort=-created_at"

六、常见问题

6.1 RESTful一定要严格遵守吗?

不一定。RESTful 只是建议的风格,不是强制标准。实际工作中,很少有 API 能完美符合所有规范。

比如有些团队就喜欢所有接口都用 POST,URL 里带动词:

复制代码
POST /api/user/getList
POST /api/user/add
POST /api/user/delete

这种写法虽然不 RESTful,但只要团队达成一致、用得舒服,也没问题。

6.2 PUT和PATCH有什么区别?

方法 语义 示例
PUT 完整替换资源 需要传用户的所有字段
PATCH 部分更新资源 只传需要修改的字段
python 复制代码
# PUT - 需要完整数据
PUT /users/1
Body: {"name": "张三", "email": "new@example.com", "age": 26}

# PATCH - 只传要改的
PATCH /users/1
Body: {"name": "张三丰"}

6.3 返回的状态码怎么选?

场景 状态码
查询成功 200 OK
创建成功 201 Created
删除成功 204 No Content
参数错误 400 Bad Request
未登录 401 Unauthorized
无权限 403 Forbidden
资源不存在 404 Not Found
服务器错误 500 Internal Server Error

6.4 URI应该用单数还是复数?

推荐用复数

复制代码
✅ /users      用户资源集合
✅ /users/1    用户集合中 ID 为 1 的资源

❌ /user/1     不推荐

但如果资源确实只有一个(比如当前登录用户),可以用单数:

复制代码
GET /user/me      当前登录用户
GET /settings     当前用户的设置(只有一份)

七、总结

本文介绍了 RESTful API 的核心概念和 FastAPI 实现,重点包括:

  1. REST的含义 :表现层状态转移,一种 API 设计风格
  2. 核心原则URI 用名词、HTTP 方法表示动作、无状态、统一响应格式
  3. FastAPI实现 :用 Pydantic 定义模型,用装饰器定义路由
  4. 实战技巧 :嵌套资源、非 CRUD 操作、统一错误处理

RESTful设计规范速查表

操作 HTTP方法 URI示例 状态码
查询列表 GET /users 200
查询单个 GET /users/{id} 200 / 404
创建 POST /users 201
完整更新 PUT /users/{id} 200 / 404
部分更新 PATCH /users/{id} 200 / 404
删除 DELETE /users/{id} 204 / 404

记住,RESTful 不是银弹,但掌握它能让你的接口更规范、更易维护。团队里大家都用同一套规范,前后端协作才能更顺畅。


热门专栏推荐

等等等还有许多优秀的合集在主页等着大家的光顾,感谢大家的支持

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😊

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🙏

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🌟

相关推荐
风象南14 小时前
Spring Boot + 执行管道:让业务流程清晰可控
后端
草莓熊Lotso14 小时前
从冯诺依曼到操作系统:打通 Linux 底层核心逻辑
linux·服务器·c++·人工智能·后端·系统架构·系统安全
Grassto14 小时前
Go 在哪里找第三方包?Module 查找顺序详解
开发语言·后端·golang
一线大码14 小时前
后端分层架构规范和标准包结构
java·后端
汪小成1 天前
Go 项目结构总是写乱?这个 50 行代码的 Demo 教你标准姿势
后端·go
Piper蛋窝1 天前
AI 有你想不到,也它有做不到 | 2025 年深度使用 Cursor/Trae/CodeX 所得十条经验
前端·后端·代码规范
哈里谢顿1 天前
事件循环介绍
fastapi
知行学思1 天前
Python配置管理完全指南:从dotenv到pydantic_settings
数据库·python·fastapi·环境变量·配置管理·pydantic·dotenv
一直都在5721 天前
Spring框架:AOP
java·后端·spring