:RESTful API 设计规范,接口命名、状态码和返回格式怎么写)
RESTful API 不是复杂理论而是一套让接口更清晰、更容易维护的设计习惯。本文用 Python 后端项目的例子讲清资源、URL、HTTP 方法、状态码、分页、筛选和统一返回格式。【一、为什么要学 RESTful API】后端项目里最容易乱的地方就是接口。如果没有规范接口可能会写成这样/getUser/createNewUser/delete_user_by_id/queryAllUserData/doLogin短期能跑长期会很难维护。前端不知道接口语义测试不知道怎么覆盖新人接手也很痛苦。RESTful API 的目的就是让接口围绕“资源”设计而不是围绕“动作”乱起名。【二、什么是资源】资源就是系统里的业务对象比如- 用户users- 文章articles- 商品products- 订单orders- 知识库knowledge-bases- 文档documentsRESTful 推荐 URL 使用名词而不是动词。推荐/users/1不推荐/getUserById?id1因为 HTTP 方法已经表达了动作URL 只需要表达资源。【三、HTTP 方法和 URL 怎么配合】以用户资源为例| 操作 | 方法 | URL | 含义 ||---|---|---|---|| 查询用户列表 | GET | /users | 查询多个用户 || 查询单个用户 | GET | /users/1 | 查询 id1 的用户 || 创建用户 | POST | /users | 新增用户 || 全量更新用户 | PUT | /users/1 | 覆盖用户数据 || 部分更新用户 | PATCH | /users/1 | 修改部分字段 || 删除用户 | DELETE | /users/1 | 删除用户 |这就是 RESTful 最常用的设计方式。【四、嵌套资源怎么设计】如果一个资源属于另一个资源可以使用嵌套路径。比如某个知识库下的文档GET /knowledge-bases/10/documentsPOST /knowledge-bases/10/documentsGET /knowledge-bases/10/documents/3意思很清楚操作的是 id10 的知识库下面的文档。但嵌套不要太深。一般最多两到三层太深说明接口设计可能过度复杂。【五、查询、分页、排序怎么写】查询参数适合放在 URL 的 query string 里。GET /articles?keywordpythonpage1page_size20GET /orders?statuspaidsort-created_at常见参数- page第几页- page_size每页多少条- keyword关键词搜索- status按状态筛选- sort排序字段返回时最好带上分页信息json{items: [],total: 125,page: 1,page_size: 20}【六、状态码怎么设计】RESTful API 不要求你背所有状态码但常用的要用对。| 状态码 | 场景 ||---|---|| 200 | 查询或普通操作成功 || 201 | 创建资源成功 || 204 | 删除成功且不返回内容 || 400 | 参数错误 || 401 | 未登录或 token 无效 || 403 | 没有权限 || 404 | 资源不存在 || 409 | 数据冲突比如邮箱已注册 || 422 | 参数格式校验失败 || 500 | 服务端异常 |新手常见问题是所有请求都返回 200然后在 JSON 里写 successfalse。这样不是完全不能用但会削弱 HTTP 状态码本身的语义。【七、统一返回格式怎么设计】项目里最好统一响应结构否则前端处理会很麻烦。一种常见格式json{code: 0,message: success,data: {}}分页接口json{code: 0,message: success,data: {items: [],total: 100,page: 1,page_size: 20}}错误响json{code: 1001,message: 用户名或密码错误,data: null}注意状态码和业务 code 可以同时存在。状态码表达 HTTP 层面的成功失败业务 code 表达更细的业务错误。【八、FastAPI 示例】pythonfrom fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModelapp FastAPI()class UserCreate(BaseModel):username: stremail: strfake_users {}app.post(/users, status_code201)def create_user(user: UserCreate):user_id len(fake_users) 1fake_users[user_id] user.model_dump()return {id: user_id, **fake_users[user_id]}app.get(/users/{user_id})def get_user(user_id: int):if user_id not in fake_users:raise HTTPException(status_code404, detail用户不存在)return fake_users[user_id]这个例子体现了- POST /users 创建用户。- GET /users/{user_id} 查询用户。- 不存在时返回 404。- 请求体用 Pydantic 校验。【九、常见坑】- URL 里混入动词/getUser、/deleteUser。- 单复数混乱有的写 /user有的写 /users。- 查询接口使用 POST导致语义混乱。- 错误码没有统一规则前端只能靠猜。- 分页没有总数前端无法做分页器。- 删除接口真的物理删除但业务上需要保留审计记录。【十、面试高频问题】【1. RESTful API 的核心思想是什么】核心思想是把系统中的对象抽象成资源用 URL 表示资源用 HTTP 方法表示对资源的操作。这样接口语义清晰便于前后端协作和维护。【2. PUT 和 PATCH 有什么区别】PUT 通常表示全量更新即客户端提交完整资源PATCH 表示部分更新只提交要修改的字段。比如用户有 username、email、avatarPATCH 可以只改 avatar。【3. 为什么要做统一响应格式】统一响应格式可以降低前端处理成本也方便统一错误处理、日志记录和接口文档生成。否则不同接口返回结构不同前端每接一个接口都要写特殊逻辑。