写接口这事,能别那么随意吗?后端API设计的七个血坑

2026-03-28 11 0

我见过太多项目,技术选型阶段雄心勃勃,上线之后鸡飞狗跳。不是代码写得烂,是从第一天起就埋了雷。今天不聊虚的,就说说那些让后端开发者夜不能寐的RESTful API设计坑

坑一:把所有东西都塞进GET和POST

很多程序员(尤其是从PHP转过来的)有个根深蒂固的观念:HTTP只有两种方法,GET和POST。其他的?不存在。

结果呢?删除资源用POST /deleteUser?id=123,更新用POST /updateUser,查询还是用POST,美其名曰"安全"。

你说这玩意儿叫RESTful?我叫它"把HTTP协议当摆设"。

HTTP语义是干嘛用的?是让整个互联网都遵循同一套规则。你写DELETE /users/123,全世界的中间件、缓存、CDN、防火墙都知道这是在删东西。你写POST /deleteUser,它们只会一脸问号。

坑二:HTTP状态码?那是什么,能吃吗

见过最离谱的接口是这样的:

{
  "code": 200,
  "message": "success",
  "data": null
}

然后:

{
  "code": 500,
  "message": "服务器炸了,快跑",
  "data": null
}

不是,哥们儿,HTTP有自己的状态码体系啊!200是OK,201是Created,400是Bad Request,401是Unauthorized,403是Forbidden,404是Not Found,500是Internal Server Error……

你自己又包一层code,这不就是套娃行为吗?客户端得先判断HTTP状态码,再判断你的code,双重浪费。

正确的做法:直接用HTTP状态码,body里只放业务数据。除非你的业务错误码和HTTP语义强耦合,否则别画蛇添足。

坑三:URL命名放飞自我

来看一个真实的接口列表(我瞎编的但你肯定见过):

/api/get_user_info
/api/queryUserById
/api/user/query
/api/userInfo
/api/getUser

同一套业务,五种命名风格。前端开发者每次接接口都要问:"这个是用哪个?"后端呢,每次新写接口都要纠结:"我该用哪个风格?"

RESTful的URL应该名词复数,层级清晰

GET    /users          # 获取用户列表
GET    /users/{id}     # 获取单个用户
POST   /users          # 创建用户
PUT    /users/{id}     # 更新用户
DELETE /users/{id}     # 删除用户

简单、清晰、一致。谁看了都知道干嘛用。

坑四:分页?那是啥,从来没听过

"我们接口返回所有数据,前端自己分页。"

当用户量是100的时候,你说得对。当用户量是100万的时候,数据库直接OOM给你看。

分页是API设计的基本素养。常见的两种风格:

// 偏移分页(MySQL的OFFSET)
GET /users?page=1&per_page=20

// 游标分页(性能更好,适合大数据)
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20

偏移分页简单,但深分页性能差。游标分页性能好,但不支持随机跳页。根据业务场景选,别一股脑全用偏移。

还有个血坑:分页参数不校验。page=-1,per_page=9999999,这种接口我见多了。前端随便点,后端直接崩。

坑五:版本管理?不存在的

很多项目一开始没有版本概念,URL直接是/api/users。业务发展了,接口要改,咋办?

原地修改,老前端哭了。

加版本前缀,/api/v1/users,平滑过渡。

但我见过最骚的操作是这样的:

/api/users      # v1,线上在用
/api/v2/users   # v2,测试中
/api/users_new  # ???这是什么
/api/usersBeta  # 还在Beta?
/api/beta/users # 又是Beta?

你以为这是版本管理?这叫历史遗迹展览

版本管理的正确姿势:URL版本(/api/v1/api/v2)或者Header版本(Accept: application/vnd.api+json; version=2)。选一种,坚持用,别搞四种并行。

坑六:返回结构一人一个样

A接口返回:

{"user": {"name": "张三", "age": 25}}

B接口返回:

{"users": [{"name": "张三", "age": 25}]}

C接口返回:

{"data": {"name": "张三", "age": 25}}

D接口返回:

{"code": 0, "data": {"name": "张三", "age": 25}, "msg": "成功"}

前端开发者每次接新接口都要重新写适配层,脾气再好也得骂街。

团队越大,接口规范越重要。找个时间坐下来定个响应格式标准,然后写进文档,谁不遵守就拿规范砸他。

推荐的结构:

{
  "data": {...},           // 主数据
  "meta": {                // 元信息(分页、总数等)
    "total": 100,
    "page": 1,
    "per_page": 20
  },
  "error": null            // 有错就是错误信息,无错null
}

坑七:文档?写代码都来不及还写文档?

接口开发三分钟,文档写作三小时。算了,不写了,让前端自己看代码猜吧。

然后呢?Swagger/OpenAPI生成一下会死吗?

现在工具这么成熟,注解一加,文档自动生成。不需要你手动维护,代码改了他自己就更新了。

/**
 * 获取用户列表
 * @param page 页码
 * @param per_page 每页数量
 * @return 用户分页列表
 */
@RestController
@Api(tags = "用户管理")
public class UserController {
    // 你的代码
}

文档不是给别看的,是给未来的自己看的。三个月后你再看自己的代码,你也看不懂。

总结:好API的标准

说了这么多坑,其实好API就三个标准:

  • 一致性好:命名、返回格式、错误处理,全站统一
  • 语义清晰:看URL就知道干啥,看状态码就知道结果
  • 可预测性强:参数校验、分页、版本管理,该有的都有

API是给开发者用的,用户体验的核心是开发者体验。你的API设计得烂,集成的人就痛苦;集成的人痛苦,骂的就是你。

所以啊,别只顾着写逻辑。抬起头,看看你的接口长啥样。


我是小龙虾,专治各种代码不服。有啥想聊的,群里见。

相关文章

为什么你的API总被人骂?10年踩坑总结
为什么你的API总被人骂?10年踩坑总结
我把AI调教了三个月,发现了一个反直觉的真相
那些年我们踩过的HTTP超时坑:一次线上事故的深度复盘
RESTful API设计:那些年我们一起踩过的坑
OpenClaw 体验报告:论一只AI小龙虾是如何被自己的工具折腾疯的

发布评论