1.2 REST 六大约束:契约的六条铁律


1.2 REST 六大约束:契约的六条铁律

本节摘要:REST 由 Roy Fielding 定义的六大约束构成:客户端服务器、无状态、可缓存、分层系统、统一接口、按需代码。其中前五条是硬约束,按需代码可选。统一接口又拆成资源识别、表示操作、自描述消息、超媒体引导四项子约束,是整套风格最难也最能带来回报的部分。本节逐条拆解每条约束在管什么、省了它是什么后果。

学习目标

阅读完本节,你应当能够:

  1. 默写出六大约束,并区分哪条可选、哪条是硬性。
  2. 对每条约束说明它锁定了什么架构决策、省掉它的代价是什么。
  3. 复述统一接口的四项子约束,并能各举一例。
  4. 判断一个接口缺少哪条约束,并预测它失效时的表现。

一、六条条款为什么凑成一份

把 REST 想象成一份施工总合同,六大约束就是六条需要在进场前逐条画钩的验收项。每条钩掉一个隐患:客户端服务器砍掉了"UI 与数据耦合"的隐患,无状态砍掉了"服务器记你上次干嘛"的隐患,可缓存砍掉了"重复拉拳脚"的隐患……它们不是独立的审美主张,而是六个保险公司——每缺一条,系统就要在特定维度上多扛一分风险。

一条条过。

二、客户端服务器:把界面和存储分开

这条约束最简单,也是整个分布式系统的地基:客户端管用户界面与交互,服务器管数据与业务逻辑,两者分开演进

  • 表现收益:UI 可以在手机、网页、桌面之间移植,因为服务器不关心你长什么样。
  • 演进收益:服务器可以独立重构、扩容,只要接口不回退,客户端跟上进度即可。
  • 代价在哪:引入了"网上传两份"的问题——客户端的意图与服务器的数据隔着网络。这正是其他约束存在的理由:没有无状态,状态夹在两边的会话里无法独立演进;没有缓存,这份网络的往返成本会被重复放大。

缺了这条约束会发生什么?服务端逻辑偷偷包含 UI 逻辑,前端任何一次改版都可能拉倒后端,契约的双方从此绑定成一体。

三、无状态:每个请求自备干粮

无状态要求:服务器在两个请求之间不保存客户端的会话上下文,每个请求都得自带处理它所需的全部信息

"无状态"被误解最多。它不是说"不能有用户登录",而是说服务器处理单个请求时,不该依赖上一个请求留下的记忆。登录状态怎么装?由客户端拿令牌(如 JWT)装在每个请求头上带走,服务器验证令牌即知你是谁,不自己留那份会话。

  • 好处一:任意一台服务器都能处理任意请求,水平扩展从此没有"粘性会话"的牵绊。
  • 好处二:服务器崩溃不丢客户端上下文,可靠性抬升。
  • 好处三:每次请求第一次握手,日志与监控天然干净。

缺了它,负载均衡后面挂多台机器时,同一用户的两次请求可能落进不同机器,机器间得同步会话,复杂度坐火箭上升。这一条的深入剧场在第 2 章的无状态契约节。

四、可缓存:响应可标定有效期

可缓存约束要求:服务器把响应标记为可缓存或不可缓存,允许客户端与中介把它们存起来复用,减少重复交互。

关键在于"明确或隐含地标记"。一个响应如果自带了 Cache-Control: max-age=3600,就是明说"这一小时内你可以直接复用,别再来烦我"。如果有条件缓存,还可以配合 ETagLast-Modified 做验证式缓存,这个机制第 3 章缓存契约节会整套展开。

缺了它,热门接口的每次查询都穿透网络打到数据库,读多写少的场景下服务器会在没必要的地方被压垮。HTTP 原生给了缓存这套工具,REST 只是要求你善用它。

五、分层系统:中间可以垫东西

分层系统要求:客户端不知道也不在乎自己面对的是最终服务器还是中间层

负载均衡器、反向代理、网关、共享缓存、安全过滤,这些中间件可以被静默插入,客户端看到的仍是同一个入口。这让系统的可伸缩性与安全策略有了独立的扩展空间——加一个缓存层给全站提速,客户端毫不知情。

缺了它,客户端如果硬编码了"我连接的就是最终服务器",那任何中间一跳都可能让响应里泄露"其实有个代理"的内部信息,改集群结构就得动客户端。

六、统一接口:最难也最值钱的条款

统一接口是六条里唯一"既简化系统又允许独立演进"的双赢条款,也是实践中最容易被打折的一条。它由四项子约束组成:

  1. 资源识别:每个资源有唯一标识,通常是一个 URI。客户端用它引用资源。
  2. 通过表示操作资源:客户端不直接改资源,而是取下它的 JSON 表示,改完用 PUT 或 PATCH 传回去。客户端只要掌握表示的字段,加上 Content-TypeContent-Location 等元数据,就足以操作资源。
  3. 自描述消息:每条消息自带足够信息说明自己怎么被处理——请求里带方法、URI、头、体;头里 Content-Type 说明体是什么格式。客户端不需要查别的文档就能解读这条消息。
  4. 超媒体作为应用状态引擎(HATEOAS):服务器在表示里带上 _links,像路标一样引导客户端下一步能做什么。

四项子约束的价值排序值得先说透:资源识别和表示操作是"及格线";自描述消息接近及格线但经常被忽略;HATEOAS 是满分级,绝大多数真实 API 做不到,第 2 章会专门讲它。

{ "id": 42, "status": "paid", "_links": { "self": "http://api.example.com/order/42", "cancel": "http://api.example.com/order/42/cancel", "invoice": "http://api.example.com/order/42/invoice" } }

上面这个订单表示里,_links 就是超媒体引导——告诉客户端"你能撤销这个订单、能查它的发票",客户端据此导航,而不用把 URI 硬编码进客户端代码。

⚠️ 常见坑:把"有 _links 字段"等同于做了 HATEOAS,结果链接只是装饰、没驱动客户端的行为。超媒体是"客户端靠链接活",不是"响应里多几个网址"。

七、按需代码:可选的那条

按需代码允许服务器给客户端下发一段可执行代码(比如浏览器里的脚本),临时扩展客户端能力。Web 浏览器里的脚本执行就是它的典型体现。

它是六条里唯一可选的一条——因为下发可执行代码会破坏"客户端逻辑稳定"的预期,换来的是灵活性。绝大多数 API 不必上它,直接省略即可,省略不会让你失去 RESTful 的资格。

💡 关键直觉:把这六条想象成验收表:前五条该勾的一律勾,第六条结合场景决定。真正决定一套 API 成色的,是统一接口那四项子约束做到了几成。

本节要点回顾

  • 要点一:客户端服务器、无状态、可缓存、分层系统、统一接口是五条硬约束。
  • 要点二:按需代码是唯一可选条款,多数 API 可省略。
  • 要点三:无状态是"不带会话",用令牌让请求自备干粮,不是"不能登录"。
  • 要点四:可缓存要求响应明确标记可否缓存、有效期多久。
  • 要点五:统一接口四项子约束中,HATEOAS 是最难也最能带来解耦回报的。
  • 要点六:判定 RESTful,看五条硬约束尤其统一接口做到几成,而非看投没投 JSON。

下一节我们把六条契约拿去市场上比价,看看什么场景值得签、什么场景签了反而亏。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U