RESTful 接口概述

聊 REST 之前,我先问个问题:你写 API 的时候,是不是也经常跟同事吵“这个接口该用 GET 还是 POST”?我以前在团队里就因为这个吵过好几次。后来想明白了,不是因为谁对谁错,而是大家对 REST 的理解不太一样。今天咱们就把 RESTful 接口这块理清楚——REST 风格、HTTP 方法、核心设计原则,我会结合自己踩过的坑来讲。

REST 架构风格

REST,全称是 Representational State Transfer,翻译过来叫“表述性状态转移”。这名字挺绕,说白了就是一种设计 Web 接口的风格。它不强制你用特定的协议或工具,但定了一套约束——只要你遵守这些约束,你的 API 就是 RESTful 的。

我记得 2016 年刚接手一个电商项目,负责人说“我们要做 RESTful API”。结果我看他们接口:订单列表用 GET /order/list,删除订单用 GET /order/delete?id=123。这哪是 REST 啊?这是 RPC 披了个 REST 的马甲。

RESTful 架构请求-响应流程 RESTful 架构请求-响应流程 客户端 API 网关 路由分发 控制器 服务层 数据存储 从左到右:客户端发起请求 → API 网关校验 → 路由分发到控制器 → 服务层处理业务 → 数据存储 每一层都保持无状态通信,资源通过 URI 唯一标识,这就是 REST 的核心骨架。
踩坑提醒: 千万不要把 RESTful 当成“用 HTTP 调个接口”就行。我见过有人把所有操作都塞进 POST /api,用请求体里的 action 字段区分增删改查——那叫 RPC 风格,不叫 REST。

HTTP 方法与资源操作映射

RESTful 接口里,HTTP 方法就是动词,资源 URI 就是名词。常用的就这五个:

HTTP 方法 操作类型 典型 URI(以用户资源为例) 响应状态码
GET 查询/读取 GET /users 或 GET /users/{id} 200 OK
POST 创建新资源 POST /users 201 Created
PUT 完全替换资源 PUT /users/{id} 200 OK 或 204 No Content
PATCH 部分更新资源 PATCH /users/{id} 200 OK
DELETE 删除资源 DELETE /users/{id} 204 No Content

注意 PUT 和 PATCH 的区别。一次重构的时候,我用 PUT 做部分更新,结果下游用旧数据把整条记录覆盖了……自那以后我再也不敢把 PUT 当成“更新”来用,它本质是“替换”。PATCH 才是部分更新,不过很多框架对 PATCH 支持不友好,得自己写序列化逻辑。

经验之谈: 我建议初学的朋友严格遵循“GET 查、POST 增、PUT 全量替换、PATCH 局部修改、DELETE 删”。等到团队形成默契了,再考虑是否放宽(比如用 POST 替代部分 PUT 场景)。

RESTful 设计原则归纳

光知道 HTTP 方法还不够,RESTful 还有几条硬性原则。我把它们总结成一张表,每条后面附一句我的真实体会。

原则 说明 我的经历
资源导向 用名词定义 URI,比如 /orders,不用动词 /getOrders 以前接手过一个项目,URI 全是 /api/getOrderList,改起来想吐血。
无状态 每个请求包含全部上下文,服务端不存会话 我们做支付回调时,一开始把用户状态存在 session 里,结果横向扩展后全乱套了。
统一接口 用标准 HTTP 方法 + 标准状态码 + 标准媒体类型 我习惯让所有接口都返回 application/json,版本号放在 Accept 头里。
超媒体驱动(HATEOAS) 响应中返回链接,指导客户端下一步操作 真正做 HATEOAS 的项目很少,但小圈子内用 _links 字段很管用。
分层系统 客户端不知道它直接连的是服务器还是网关 我们在网关层做了流量染色和国密验签,客户端无感知,这很优雅。
核心总结: RESTful 不是银弹,但它能让你给 API “立规矩”。有了规矩,团队协作就不容易跑偏。

实际接口长什么样?

我们写个简单的示例,请求一个订单资源:

# 创建订单
POST /orders
Content-Type: application/json
Accept: application/json

{
  "userId": 1024,
  "items": [
    {"sku": "B-001", "quantity": 2},
    {"sku": "B-002", "quantity": 1}
  ]
}

响应:

HTTP/1.1 201 Created
Location: /orders/3001
Content-Type: application/json

{
  "orderId": 3001,
  "userId": 1024,
  "status": "pending",
  "totalAmount": 45.00,
  "_links": {
    "self": {"href": "/orders/3001"},
    "payment": {"href": "/orders/3001/payment"}
  }
}

你看,响应里给了 _links,客户端接下来可以直接去 /orders/3001/payment 发起支付,不需要从页面里拼 URL。这就是超媒体驱动的味道——虽然现实中很少有团队完全做到,但熟悉这个思想对理解 REST 很有帮助。

注意: 千万别把业务逻辑动词塞进 URI。/order/cancel 就是反例,正确的做法是 PATCH /orders/{id} 并带上 {"status": "cancelled"}。我第一次写 REST API 时也犯过这错,后来被 code review 打回来改的。

本章小结

RESTful 接口设计说白了就是 “用 HTTP 规范来表达资源操作”。记住三点:资源用名词、动词用方法、状态码要准确。后面几章我们会结合国密算法来封装这些接口——签名、验签、加密、解密,都会用到今天讲的 REST 原则。嗯,一开始可能觉得约束多,但用习惯了你会发现,RESTful 风格能让你的接口像文档一样清晰。