# API 设计:前后端的通用语言 > 💡 **学习指南**:这一章我们聊聊前后端如何高效对话。如果你被后端接口的命名搞晕过,或者不知道该返回 200 还是 404,这篇文章就是为你准备的。我们将通过一个交互式 Demo,带你理解 RESTful API 的设计精髓。 --- ## 0. 先问一个问题:你有没有经历过这些噩梦? **场景一:接口猜谜** 后端给你一个接口 `/getUser`,你调用了,返回 `null`。 你是传错了参数?还是数据库没数据?还是服务器崩了?完全不知道。 **场景二:状态码撒谎** 你收到了一个 HTTP 200 OK 的响应,心想“稳了”。 结果打开 Body 一看: ```json { "code": 500, "msg": "系统内部错误", "data": null } ``` 浏览器缓存了它,监控系统认为它成功了,只有你的前端代码在风中凌乱。 **场景三:版本地狱** 项目迭代了三年,你的代码里充满了这样的 URL: - `/api/v1/user/update` - `/api/v2/user/update_new` - `/api/user/update_final_real` --- **API 设计就是为了解决这些问题。** 它就像餐厅的菜单和点餐流程:规定了我们**怎么点菜(请求)**、**怎么上菜(响应)**、**没菜了怎么办(错误处理)**。 目前最流行的设计风格是 **RESTful**。 --- ## 1. 核心概念:RESTful 是什么? REST (Representational State Transfer) 听起来很学术,其实核心就三句话: 1. **资源 (Resource)**:网络上的所有东西都是资源(用户、订单、商品)。 2. **统一接口 (Uniform Interface)**:用标准的 HTTP 方法(GET, POST, DELETE)来操作这些资源。 3. **无状态 (Stateless)**:每次请求都包含所有必要信息,服务器不记“你是谁”(除非你带了 Token)。 ### 比喻:餐厅点餐 - **URL 是桌号**:`/tables/5` (资源地址) - **HTTP 方法是动作**: - `GET`:看菜单 - `POST`:下单 - `PUT`:换一桌菜 - `DELETE`:吃完走人 --- ## 2. 交互演示:RESTful API 全流程 别光听概念,我们来动手玩一下。 下面是一个模拟的“用户管理系统”。试着点击不同的场景,观察 **客户端发出了什么** 以及 **服务端返回了什么**。 ### 💡 观察重点 1. **URL 是名词**:注意看 URL 都是 `/users` 或者 `/users/1`,没有动词(如 `/getUsers`)。因为 HTTP 方法(GET/POST)已经表示了动作。 2. **状态码会说话**: - 创建成功返回 `201 Created`,而不是 200。 - 删除成功返回 `204 No Content`(没有 Body)。 - 找不到返回 `404 Not Found`。 3. **复数形式**:通常使用 `/users` 而不是 `/user`,表示这是“用户集合”下的资源。 --- ## 3. 设计黄金法则 ### 3.1 URL 设计:让路径清晰 | 法则 | 正确 ✅ | 错误 ❌ | 原因 | | :--- | :--- | :--- | :--- | | **用名词,不用动词** | `GET /products` | `GET /getProducts` | HTTP 方法已经是动词了 | | **用复数** | `/users/1` | `/user/1` | 保持一致性,`/users` 代表集合 | | **层级不要太深** | `/users/1/orders` | `/users/1/orders/2/items/3` | 超过 3 层建议拆分或用查询参数 | | **使用连字符** | `/user-profiles` | `/userProfiles` | URL 对大小写敏感,连字符更易读 | ### 3.2 HTTP 方法:动作要有语义 - **GET** (查):**安全且幂等**。不管调用多少次,服务器状态不变。 - **POST** (增):**不安全,不幂等**。调用 10 次可能创建 10 个用户。 - **PUT** (改-全量):**幂等**。把 ID=1 的用户替换为新数据,替换 10 次结果一样。 - **PATCH** (改-局部):通常用于只修改一个字段(如只改密码)。 - **DELETE** (删):**幂等**。删除 ID=1 的用户,删 1 次和删 10 次,结果都是“用户没了”。 ### 3.3 状态码:别只用 200 | 类别 | 状态码 | 含义 | 场景 | | :--- | :--- | :--- | :--- | | **2xx 成功** | 200 OK | 通用成功 | GET, PUT | | | 201 Created | 创建成功 | POST | | | 204 No Content | 成功但无返回 | DELETE | | **4xx 客户端错** | 400 Bad Request | 参数错 | 必填项没填,格式不对 | | | 401 Unauthorized | 未登录 | 没有 Token 或 Token 过期 | | | 403 Forbidden | 无权限 | 普通用户想删管理员 | | | 404 Not Found | 找不到 | URL 错了或 ID 不存在 | | **5xx 服务端错** | 500 Internal Error | 崩了 | 代码抛异常了,数据库挂了 | --- ## 4. 总结 好的 API 设计是**“自解释”**的。 当你的前端同事看到 `DELETE /api/orders/123`,他不需要问你,就应该知道: 1. 这是一个删除操作。 2. 操作对象是 ID 为 123 的订单。 3. 如果成功,应该收到 204 或 200。 4. 如果失败,应该去看状态码是 4xx 还是 5xx。 这就是**约定优于配置**的力量。