游乐游手机版
首页/AI教程/文章详情

为什么传统REST接口设计仍是后端系统最稳基本功

时间:2026-06-15 15:37
REST基于HTTP协议,以资源为核心建模,URL标识资源,HTTP方法(GET POST等)表达操作,统一状态码与错误结构,配合分页、版本管理和权限校验,是后端系统最简洁、可扩展且稳定的接口设计方式。

过去几年,GraphQL、gRPC、tRPC、BFF、AI Agent 接口一个个轮番登场,热闹得很。但真到了大多数业务系统里,REST 依然是那个最常见、最容易落地、协作成本最低的选择。

原因非常简单——REST 足够朴素。

它直接跑在 HTTP 上,不需要客户端和服务端去约定什么复杂的协议,也不用团队一上来就搭好整套 IDL、网关和代码生成体系。前端、移动端、后端、测试、运维,谁看谁懂。只要接口文档把 URL、Method、参数、返回值和状态码写清楚,大家基本就能愉快地合作了。

但也正因为 REST 看起来简单,很多项目最后会写成“披着 HTTP 外衣的随意 RPC”。所有接口都写成 POST /doSomething,状态码永远返回 200,错误都塞在 message 里,资源命名随心所欲,分页和过滤各搞一套。短期来看跑得挺顺,但时间一长,维护起来简直噩梦。

所以我们今天不聊课本那套,就说说传统业务系统里真正实用的 REST 设计习惯。

REST 的核心:围绕资源设计

REST 最核心的思想,不是用 JSON 传数据,也不是通过 HTTP 调接口,而是围绕资源来建模。资源可以是用户、订单、商品、文章、评论、文件、任务。设计接口时,URL 表达资源是什么,HTTP Method 表达对这个资源做什么动作。

比如订单资源:

GET /orders        查询订单列表
POST /orders       创建订单
GET /orders/1001   查询单个订单
PUT /orders/1001   整体更新订单
PATCH /orders/1001 部分更新订单
DELETE /orders/1001 删除订单

你看,看到接口就大概知道在操作什么资源、做什么动作,清晰明了。

相比之下,下面这种写法就很不 REST 了:

POST /getOrderList
POST /createOrder
POST /updateOrderStatus
POST /deleteOrder

不是说不能用,而是把动作都塞进 URL 里,HTTP Method 完全失去了语义。接口少的时候无所谓,系统一复杂,命名就乱成一锅粥了。

一个典型 REST 请求流程

image.png

一个合格的 REST 接口,绝不只是 Controller 里能返回数据那么简单。在请求流程的每一层,都要有清晰的职责边界:网关负责通用流量,Controller 处理协议和参数,Service 执行业务逻辑,Repository 做数据访问,DTO 负责对外表达。

HTTP Method 别乱用

传统 REST 里最容易混乱的,就是 Method。

常见约定如下:

Method含义是否应该幂等
GET查询资源
POST创建资源或提交动作
PUT整体替换资源
PATCH局部更新资源通常是
DELETE删除资源

幂等的意思很简单:同一个请求执行一次和执行多次,最终结果是一样的。

比如:

DELETE /orders/1001

执行一次是删除订单,再执行一次,仍然是“订单不存在”,最终状态没有变化,所以它是幂等的。

而:

POST /orders

每执行一次都可能创建一个新订单,所以不是幂等的。

实际业务里,有些动作很难完全归类为一个资源,比如支付订单、取消订单、提交审批。这时候就把动作建模成子资源或者业务操作:

POST /orders/1001/payment
POST /orders/1001/cancellation
POST /approval-tasks/2001/submission

千万别为了形式上的完美,硬把所有业务都拧成一个 PUT /orders/1001。工程设计既要讲语义,也要讲可读性。

状态码不要永远是 200

很多系统喜欢这么干:响应体里 code 是 500,message 写着 server error,但 HTTP 状态码却永远是 200 OK。这对调试、网关、监控、SDK、缓存都很不友好,简直就是给自己挖坑。更合理的做法是:让 HTTP 状态码表达协议层结果,让响应 body 表达业务细节。

常用状态码:

状态码含义
200请求成功
201创建成功
204成功但无响应体
400参数错误
401未登录或 token 无效
403已登录但无权限
404资源不存在
409资源冲突
422语义校验失败
429请求过多
500服务端异常

错误响应可以统一成这样:

{
    "error": {
        "code": "ORDER_STATUS_INVALID",
        "message": "当前订单状态不允许取消",
        "requestId": "req_01HZX8K7"
    }
}

code 给程序判断,message 给人看,requestId 给排障用。

查询、分页、排序,统一约定

列表接口是 REST 系统里最容易跑偏的地方。

建议大家统一使用 query string:

GET /orders?status=paid&createdAfter=2026-05-01&page=1&pageSize=20&sort=-createdAt

常见约定:

page / pageSize:传统分页
limit / offset:偏移分页
cursor / limit:游标分页
sort=-createdAt:按创建时间倒序
sort=createdAt:按创建时间正序

如果数据量大,或者列表会频繁新增,游标分页比 page 分页更稳:

GET /orders?cursor=eyJpZCI6MTAwMX0=&limit=20

返回:

{
    "items": [],
    "nextCursor": "eyJpZCI6MTAyMX0=",
    "hasMore": true
}

千万别让每个接口各自发明一套分页字段。统一约定能直接降低前后端沟通成本。

接口版本管理必须提早规划

一旦接口被客户端用上了,就不能随意改动了。

常见的版本方式有三种:

/api/v1/orders
Accept: application/vnd.company.v1+json
?apiVersion=1

业务系统最常用的是 URL 版本:

GET /api/v1/orders

它不一定最优雅,但最直观,网关、文档、测试都容易处理。

版本管理的重点不是路径怎么写,而是不要破坏已有客户端。新增字段通常是兼容的,删除字段、改变字段含义、改变枚举值、改变错误结构,都是高风险变更。

鉴权和权限,不是一回事

REST 接口里经常混淆两个概念:

Authentication:你是谁
Authorization:你能做什么

前者通常通过 token、session、API key、OAuth2 完成。后者要结合角色、资源归属、租户、数据权限去判断。

比如:

GET /orders/1001
Authorization: Bearer 

服务端不止要验证 token 是否有效,还要判断当前用户有没有权限访问这个订单。很多系统只做登录校验,不做资源级权限校验,结果只要用户猜到 ID,就能越权访问别人数据,这是重大安全漏洞。

REST 的优点和它的天花板

REST 的优点很明显:

  • 基于 HTTP,生态成熟;
  • 对人友好,调试方便;
  • 对缓存、袋里、网关支持好;
  • 前后端协作成本低;
  • 适合 CRUD 和大多数业务接口。

但它也有自己的天花板。

当客户端需要灵活选择字段、组合多个资源时,GraphQL 可能更合适。

当服务间追求高性能、强类型、低延迟通信时,gRPC 是更好的选择。

当系统内部动作强过程化,比如复杂工作流、批处理任务、命令调度时,RPC 风格也未必比 REST 差。

REST 不是银弹,它最适合稳定、清晰、资源导向的业务接口。

实践建议

  • URL 用名词,不要用动词。 GET /users/1 而不是 GET /getUser
  • 状态码要有语义,不要全部返回 200。
  • 请求和响应 DTO 要稳定,不要直接暴露数据库实体。
  • 分页、排序、错误结构、时间格式要统一。
  • 敏感操作要考虑幂等。 比如支付、退款、创建订单,可以使用 Idempotency-Key
  • POST /payments
    Idempotency-Key: 8f0b2b4a-7f2e-4d8a
  • 接口文档要和代码一起维护。 OpenAPI / Swagger 不一定完美,但比口口相传可靠。

总结

传统 REST 之所以还在大量系统里大规模使用,不是因为它够新,而是因为它够稳。它把接口设计约束在一个非常简单的模型里:资源用 URL 表达,动作由 HTTP Method 表达,结果由状态码表达,细节由 JSON body 表达。

真正写好 REST,不靠什么复杂框架,而靠一致性。命名一致,状态码一致,错误结构一致,分页一致,权限判断一致,系统就会越来越好维护。

新技术当然值得学,但 REST 依然是后端工程师绕不开的基本功。很多系统的问题,不是 REST 过时了,而是从一开始,就没认真设计过 REST。

来源:https://developer.aliyun.com/article/1741399
上一篇Semgrep快速入门指南,三分钟轻松代码扫描 下一篇taste-skill实战:实用技巧彻底降低AI前端交互的机械感
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Windows Docker Desktop RabbitMQ生产级部署完整指南
AI教程 · 2026-06-29

Windows Docker Desktop RabbitMQ生产级部署完整指南

前言 在 Windows 本地开发环境中,直接安装 RabbitMQ 确实颇为周折:需要单独配置 Erlang 运行环境、手动管理环境变量、服务启停全凭手工操作。更令人困扰的是,版本兼容冲突、端口占用、环境不一致等问题层出不穷。笔者见过不少开发者为搭建环境就得耗费整整半天时间。 相比之下,借助 Do

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践
AI教程 · 2026-06-29

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践

先分享一个切实感受。过去两年,我们与福建制造企业合作较为频繁,发现一个非常突出的现象:超过80%的企业官网,产品参数仍然存放在PDF或图片中。AI爬虫?根本无法抓取。这些企业技术实力不弱、资质证照齐全、应用案例也丰富,但在AI搜索这一全新战场上,它们几乎处于隐身状态。 一、一个正在发生的行业变化 A

阿里云Token Plan团队版功能价格与省钱购买指南
AI教程 · 2026-06-29

阿里云Token Plan团队版功能价格与省钱购买指南

阿里云百炼近期推出了名为“Token Plan 团队版”的全新服务,这一服务专为企业与开发者量身打造,定位为AI大模型订阅平台。通过引入Credits作为统一计量单位,将文本生成、图像生成等多模态AI能力纳入单一计费体系,同时无缝兼容主流AI编程工具及智能体(Agent)生态系统。其核心亮点包括:全

阿里云物联网.NET Core客户端位置信息上报
AI教程 · 2026-06-29

阿里云物联网.NET Core客户端位置信息上报

阿里云物联网平台的位置服务并非一个完全独立的功能模块。位置信息可包含二维坐标与三维坐标,而位置数据的来源本质上是借助设备属性进行上传。换言之,若要让设备上报位置,您需先将其视为一个普通属性进行处理。 1)添加二维位置数据 操作过程十分简洁。进入数据分析 → 空间数据可视化 → 二维数据,点击添加,将

年阿里云服务器选型配置与网站部署全攻略
AI教程 · 2026-06-29

年阿里云服务器选型配置与网站部署全攻略

2026年,阿里云服务器生态已高度成熟,形成了清晰的轻量应用服务器与ECS云服务器两大产品阵营。无论你是计划搭建个人博客、企业官网,还是运营电商平台、进行应用开发,基本都能找到理想的解决方案。本指南将从服务器选型、配置选择、部署流程到安全运维,系统梳理2026年最实用的操作要点,帮助你少走弯路,让网