【Web API】RESTful API接口规范

【Web API】RESTful API接口规范

文章目录

一、 RESTful API接口规范

REST:英文REpresentational State Transfer直译为表现层状态转移

RE(Representational)表现层
RE(Representational)表现层是指资源(Resource)的表现形式,
资源(Resource)指要操作的数据对象,比如用户、订单、商品、分类、文章、等等。用户列表列表是一个资源;某个具体的用户也是一个资源。表现层是指资源呈现出来的具体格式。比如同一个用户资源,可以用Json格式返回给客户端,也可以用XML格式返回,这就是不同的表现形式。

S(State)状态
ST(State)状态是指资源在某一时刻的状态。比如你登录网站后,服务器会在内存中记住你是谁,之后在网站上操作就不用再次登录了,这就是有状态。而无状态就是服务器不记录客户端的任何信息,每次请求都是独立的。

T(Transfer)转移
要注意转移是双向的,当你用GET请求时,服务器把资源的状态转移给客户端;当你用POST请求时,客户端把资源的新状态转移给服务器,从而改变服务器上资源的状态,

组合起来REST(Representational State Transfer)是一种软件架构风格,让客户端和服务器通过统一的接口以无状态的方式互相传递资源的表现层数据来查询或变更资源状态,而ful是个后缀就像powerful充满力量的一样,表示充满某个特性的。因此RESTful API 是指符合 REST 架构风格的API

注意:它不是协议,不是标准,不是强制规范,只是一种建议的设计风格,你可以遵循,也可以不遵循。


例如:你要做一个用户管理系统,对用户信息进行增删改查,用RESTful 风格的 API,如下所示:

  • GET /users/123 获取ID为1231用户
  • POST /users 创建新用户
  • PUT /users/123 修改用户 123
  • DELETE /users/123 删除用户 123

比较

操作非 RESTfulRESTful
获取用户POST /getUser?id=1GET /users/1
创建用户POST /createUserPOST /users
更新用户POST /update_userPUT /users/1
删除用户POST /delete/userDELETE /users/1

二、 构造RESTful API

2.1 客户端发送请求

2.1.1 确定资源

资源用URI统一资源标识符来表示,核心规则是用名词来表示资源,不用动词

  • 名称复数表示资源集合,如:
    • /users 表示用户列表;
    • /products 表示商品列表
  • 具体某个资源,就加上 ID ,如:
    • /users/123 表示ID为123的用户
  • 支持嵌套,如:
    • /users/123/orders 获取用户123的所有订单

注意:不建议嵌套层级太深


2.1.2. 选择动作

是指处理资源的方式, RESTful API主要通过不同的HTTP方法来表示增删改查操作。

  • GET /users/123 获取ID为1231用户
  • POST /users 创建新用户
  • PUT /users/123 修改用户 123
  • DELETE /users/123 删除用户 123

GET 查询资源

  • GET /users — 查询所有用户
  • GET /users/123 — 查询ID为1231用户

POST 创建 资源

  • POST /users — 查询所有用户

PUT 完整更新资源
调用时需要提供资源的所有字段,多次执行结果相同(幂等性)。

  • PUT /users/123— 完整更新用户123

PATCH 部分更新资源
通常用于更精细的操作。

  • PATCH /users/123 — 只更新用户123的某些字段

DELETE 删除资源

  • DELETE /users/123 — 删除用户123

2.1.3. 添加查询条件(可选)

有时我们需要更精确的筛选数据。

GEThttps://api.codefather.cm/users 
  • 分页/users?page=2&limit=10 — 查询第2页,每页10条用户数据
  • 筛选/users?gender=male&age=25 — 查询性别为男性,年龄为25的用户
  • 排序/users?sort=created_at&order=desc — 按照创建时间倒序排列用户

查询参数本身不是RESTful特有的,但Restful 风格强调把筛选排序分页这些操作都通过URL参数来表达,而不是在请求体里面传一堆复杂的Json对象。

Restful 风格

GEThttps://api.codefather.cm/users?age=25&page=2&sort=created_at 
  • 筛选 age=25
  • 分页 page=2
  • 排序 sort=created_at

非Restful 风格 - JSON对象 - 分页

{"operation":"getUsers","params":{"pagination":{"pageNumber":1,"pageSize":10}}}

非Restful 风格 - JSON对象 - 过滤

{"action":"searchUsers","filters":[{"field":"gender","operator":"equals","value":"male",},{"field":"age","operator":"equals","value":"25",}]}

非Restful 风格 - JSON对象 - 排序

{"command":"listUsers","options":{"sortBy":"create_at","sortOrder":"desc",}}

Restful 风格 的筛选排序分页URL 更清晰明了,而且浏览器CDN代理服务器都能直接根据URL来缓存响应结果,不同的URL可以分别缓存,更容易区分。


缓存示例1

  • /users?page=1
idnamegae
1张三25
2李四26

缓存示例2

  • /users?page=2
idnamegae
3王五27
4赵六28

2.1.4. 版本控制

随着业务发展,接口需要更新升级,为了不影响老用户,可以在URI中标明版本,这样老用户用v1的接口,新用户用v2的接口,互不影响。

  • /v1/users — 第一版用户接口
  • /v2/users — 第二版用户接口

完整示例

GEThttp://api.codefather.cm/v2/users?age=25&page=2&sort=created_at 

2.1.5. 保持无状态

无状态 (Stateless) 是 RESTful 架构的核心约束之一。 其含义是,服务器不应保存客户端的会话状态。每个来自客户端的请求都必须包含处理该请求所需的全部信息(如身份凭证、上下文等)。

典型实现方式是:

  1. 用户登录后,服务器生成一个唯一的身份凭证(如 Token),并将其返回给客户端。
  2. 此后客户端的每一个请求都必须在HTTP标头(如 Authorization: Bearer <token>)中携带此凭证。
  3. 服务器不关心请求之间的关联,仅根据当前请求提供的 Token 和参数进行验证、处理并返回响应。

请求标头

GET/orders Header: Authorization: Bearer xxx 

这样做带来的关键优势:

  • 极高的可扩展性: 由于请求完全独立,无需会话亲和性(Session Affinity),任何服务器实例都能处理任何请求。这使得通过简单地增加服务器节点来实现水平扩展变得非常容易。
  • 简化服务器设计: 服务器无需实现复杂的状态同步、会话存储和清理机制,降低了复杂度和资源消耗。
  • 提升可靠性: 单点故障的影响更小。客户端请求可以无缝地由其他可用服务器处理,无需担心会话丢失。
  • 便于缓存和负载均衡: 无状态的请求使得HTTP缓存机制(如CDN、反向代理)和标准的负载均衡策略能更高效地工作。

因此,“无状态”是构建大规模、高性能、可伸缩分布式服务的基石,它将状态管理的责任转移给客户端,使服务器集群变得简单而强大。


2.2 服务端给出响应

2.2.1. 统一响应格式

目前大多数 RESTful API 基本都使用 JSON 格式,因为轻量、容易解析,但并不是强制的,也可以用XMLHTML 等格式,

JSON格式

{"id":123,"name":"张三","email":"[email protected]",}

XML格式

<?xml version="1.0" encoding="UTF-8"?><user><id>123</id><name>张三</name><email>[email protected]</email></user>

HTML格式

<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>用户信息</title></head><body><divclass="user-info "><p><strong>ID:</strong> 123</p><p><strong>姓名:</strong> 张三</p><p><strong>邮箱:</strong> [email protected]</p></div></body></html>

2.2.2. 返回合适的HTTP状态码

响应需要带上合适的状态码,前端开发者或运维人员通过查看状态码,就能快速定位问题方向

请求网址:http://api.codefather.cm/ 请求方法:GET 状态代码:200 OK 远程地址: 引荐来源网址政策:strict-origin-when-cross-origin 

HTTP 状态码有很多,大致可以分为5类:

  1. 1xx 系列:信息提示(用的少,了解即可)
    • 100 Continue:继续请求
  2. 2xx 系列:成功
    • 200 OK:请求成功,正常返回数据(用于 GET、PUT、PATCH)
    • 201 Created:创建成功(用于POST 请求),通常会在响应头的Location 中返回新的资源地址URI
    • 202 Accepted:请求已接受,但还在处理中(常用于异步操作)
    • 204 No Content:请求成功,但无返回数据(常用于 DELETE )
  3. 3xx 系列:重定向
    • 301 Moved Permanently:请求的资源已永久移动到新位置
    • 302 Found:请求的资源已临时移动到新位置
    • 304 Not Modified:资源未修改,客户端可以使用缓存。
  4. 4xx 系列:客户端错误
    • 400 Bad Request:请求参数格式错误
    • 401 Unauthorized:为验证身份,需要登录
    • 403 Forbidden:已认证但没有权限访问
    • 404 Not Found:资源不存在
    • 405 Method Not Allowed:请求方法不被允许(比如对只读资源用DELETE)
    • 409 Conflict:请求冲突(比如尝试创建已存在的资源)
    • 422 Unprocessable Entity:请求格式正确,但语义错误(比如邮箱格式不对)
    • 429 Too Many Requests:请求过于频繁,触发限流
  5. 5xx 系列:服务器错误
    • 500 Internal Server Error:服务器内部错误
    • 502 Bad Gateway:网关错误(服务器作为网关时,从上游服务器收到无效响应)
    • 503 Service Unavailable:服务器暂时不可用(通常是服务器维护或过载)
    • 504 Gateway Timeout:网关超时

三、RESTful 六大约束

1. Client-Server(客户端-服务器分离)
前后端各干各的活,前端负责展示,后端负责数据处理,互不干扰。

2. Stateless(无状态)
每次请求都是独立的,服务器不保持客户端的会话信息,必要信息都在请求中。

3. Cacheable(可缓存)
服务器的响应可以被标记为可缓存,客户端可以重用缓存数据,减少服务器压力。提升性能。

4. Layered System(分层系统)
客户端不需要知道直接连接的是服务器还是中间层,系统可以灵活加代理、网关、负载均衡器等。

5. Uniform Interface(统一接口)
所有资源都通过统一的接口访问,降低理解成本,提高可维护性。

6. Code-On-Demand(按需代码)
可选性,服务器可以返回可执行代码(比如JavaScript)给客户端执行,但实际工作中很少用。

很少有API能完美符合所有约束,大家可以灵活自行组合。甚至可以想下面所示代码一样,都用POST + 动词一把梭。

//示例1:用户接口 app.post('/user',(req,res)=>{const{do,data}=req.body; res.json({do,result:db[do](data)});})//示例2:订单接口@app.post('/order') def handle(req):returnglobals()[f"{req.verb}_order"](req.data)//示例3:文件接口 app.post('/file',(req,res)=>{const{act,...args}=req.body; res.json({act,data:actions[act](args)});})

只要团队达成一致,舒服就行。就像刚才那个支付订单的例子.
虽然用名词符合RESTful 规范,但有同学会觉得用动词更直观易懂,也没问题。

  • POST /orders/123/pay 💗
  • POST /orders/123/payments

建议养成遵循RESTful 的好习惯,写出更漂亮的接口。


四、RESTful API 开发与测试

如何快速实现和检查 RESTful API?

1. 使用开发框架
几乎所有主流的开发框架都支持 RESTful API 的开发,他们能帮你自动处理很多细节。比如:

  • JavaSpring Boot
  • PythonDjango REST Framework
  • GoGin

这些框架虽然不强制你遵循 RESTful ,但用他们的特性开发起来轻松又规范,帮你省掉大量重复代码。


2. 使用IDE 插件
比如:

  • IDEARESTful Toolkit插件 ,可以快速查看和测试接口
  • VSCodeREST Client插件,可以直接在编辑器里测试接口

3. 利用AI生成
RESTful 有明确的设计规范,而AI最擅长处理这种有章可循的东西,比如直接让 DeepSeek

描述词

帮我用`Spring Boot`,写一个用户管理的 `RESTful API`, 

你只需简单描述一下,它就能生成规范的代码
输出结果

packagecom.example.usermanagement.controller;importcom.example.usermanagement.dto.UserRequest;importcom.example.usermanagement.dto.UserResponse;importcom.example.usermanagement.service.UserService;importio.swagger.v3.oas.annotations.Operation;importio.swagger.v3.oas.annotations.Parameter;importio.swagger.v3.oas.annotations.tags.Tag;importjakarta.validation.Valid;importlombok.RequiredArgsConstructor;importorg.springframework.data.domain.Page;importorg.springframework.data.domain.Pageable;importorg.springframework.data.domain.Sort;importorg.springframework.data.web.PageableDefault;importorg.springframework.http.HttpStatus;importorg.springframework.http.ResponseEntity;importorg.springframework.security.access.prepost.PreAuthorize;importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api/v1/users")@RequiredArgsConstructor@Tag(name ="用户管理", description ="用户管理相关API")publicclassUserController{privatefinalUserService userService;@PostMapping@Operation(summary ="创建用户")@PreAuthorize("hasRole('ADMIN')")publicResponseEntity<UserResponse>createUser(@Valid@RequestBodyUserRequest userRequest){UserResponse userResponse = userService.createUser(userRequest);returnResponseEntity.status(HttpStatus.CREATED).body(userResponse);}@GetMapping("/{id}")@Operation(summary ="根据ID获取用户")publicResponseEntity<UserResponse>getUserById(@Parameter(description ="用户ID")@PathVariableLong id){UserResponse userResponse = userService.getUserById(id);returnResponseEntity.ok(userResponse);}@GetMapping("/username/{username}")@Operation(summary ="根据用户名获取用户")publicResponseEntity<UserResponse>getUserByUsername(@Parameter(description ="用户名")@PathVariableString username){UserResponse userResponse = userService.getUserByUsername(username);returnResponseEntity.ok(userResponse);}@GetMapping@Operation(summary ="获取用户列表(分页)")@PreAuthorize("hasRole('ADMIN')")publicResponseEntity<Page<UserResponse>>getAllUsers(@PageableDefault(size =20, sort ="createdAt", direction =Sort.Direction.DESC)Pageable pageable){Page<UserResponse> users = userService.getAllUsers(pageable);returnResponseEntity.ok(users);}@PutMapping("/{id}")@Operation(summary ="更新用户信息")publicResponseEntity<UserResponse>updateUser(@Parameter(description ="用户ID")@PathVariableLong id,@Valid@RequestBodyUserRequest userRequest){UserResponse userResponse = userService.updateUser(id, userRequest);returnResponseEntity.ok(userResponse);}@PatchMapping("/{id}/status")@Operation(summary ="更新用户状态")@PreAuthorize("hasRole('ADMIN')")publicResponseEntity<UserResponse>updateUserStatus(@Parameter(description ="用户ID")@PathVariableLong id,@RequestParamBoolean isActive){UserResponse userResponse = userService.updateUserStatus(id, isActive);returnResponseEntity.ok(userResponse);}@DeleteMapping("/{id}")@Operation(summary ="删除用户")@PreAuthorize("hasRole('ADMIN')")publicResponseEntity<Void>deleteUser(@Parameter(description ="用户ID")@PathVariableLong id){ userService.deleteUser(id);returnResponseEntity.noContent().build();}}

4. 生成文档
写完接口后还可以用Swagger 这类工具,自动生成漂亮的文档。直接甩给前端,对方一看就懂,还能在线测试接口,省去大量沟通成本

在这里插入图片描述

五、总结

RESTful API有以下优点:

  • 统一规范接口
  • 提高开发效率
  • 降低团队沟通成本

其他API规范 GraphQL, gRPC

Read more

飞书机器人与Claude Code交互:从手机指令到AI处理的全自动流程

飞书机器人与Claude Code交互:从手机指令到AI处理的全自动流程

飞书机器人与Claude Code交互:从手机指令到AI处理的全自动流程 * 一、背景 * 二、实现方案概览 * 三、操作步骤 * 前置准备 * 第一步:创建并进入Claude Code容器 * 配置Claude Code使用本地模型 * 测试Claude Code是否正常工作 * 第二步:安装Python依赖 * 第三步:获取飞书应用的凭证 * 第四步:编写并运行中间件脚本 * 脚本解释 * 运行脚本 * 第五步:在飞书中与机器人对话 * 常见问题 * 总结 一、背景 在日常开发中,我们经常需要快速查询代码问题、生成文档或执行简单的编程任务。如果有一款AI助手能随时响应,就像在电脑终端前一样,那该多方便!本教程将演示如何搭建一个飞书机器人,当你在手机飞书App上发送消息时,该消息会传递给运行在电脑上的Claude Code(一个智能编码助手),Claude Code处理后将结果回复到你的飞书会话中。 通过这个方案,你可以: * 在手机上随时向AI提问编程问题。 * 让AI帮你调试

基于目标偏置与双向APF-RRT*的无人机动态避障轨迹优化

1. 无人机轨迹规划:为什么传统方法在动态环境里“不够看”? 大家好,我是老张,在无人机和机器人路径规划这个领域摸爬滚打了十几年。今天想和大家聊聊一个非常实际的问题:无人机在复杂、动态的环境里,怎么才能规划出一条既安全又高效的飞行路线? 这听起来像是个科幻电影里的场景,但其实是当下无人机物流、巡检、应急救援等领域必须啃下的硬骨头。 想象一下,你操控一架无人机在布满高楼、树木,甚至还有其他飞行器的城市峡谷里穿梭。传统的路径规划方法,比如经典的 RRT(快速探索随机树) 算法,就像是一个蒙着眼睛的探险家。它会在整个空间里随机“扔飞镖”(采样点),然后尝试把飞镖落点连起来形成路径。这种方法虽然能保证最终找到一条路,但效率实在太低了,规划出的路径往往歪歪扭扭,像喝醉了酒一样,而且对动态障碍物反应迟钝。我在早期项目里没少吃这个亏,无人机要么撞上突然出现的飞鸟,要么规划的路径绕了十万八千里,电量耗尽都飞不到目的地。 后来有了 RRT* 算法,它在RRT的基础上增加了“重布线”和“父节点重选”的优化步骤,能让路径长度逐渐逼近最优,算是很大的进步。但它在面对动态环境时,依然有个核心问题:

LazyLLM 测评 | 低代码颠覆 AI 开发!代码专家智能体进阶模块实战

LazyLLM 测评 | 低代码颠覆 AI 开发!代码专家智能体进阶模块实战

摘要: LazyLLM 是商汤大装置推出的开源低代码框架,作为构建和优化多 Agent 应用的一站式开发框架,覆盖应用搭建、数据准备、模型部署、微调、评测等全流程开发环节,提供丰富的工具支持。其以模块化设计打破传统开发壁垒,通过数据流驱动重构开发逻辑,能让开发者用极简代码实现工业级复杂 AI 应用,摆脱冗余编码束缚,聚焦核心业务场景,降低 AI 应用构建成本并支持持续迭代优化。堪称 AI 开发者的 “效率神器”,其技术普惠理念为 AI 开发领域带来新的实践范式,推动了更高效的开发模式。本文将以Python编程为切入点,带你深入了解LazyLLM框架。 LazyLLM 是构建和优化多 Agent 应用的一站式开发工具,为应用开发过程中的全部环节(包括应用搭建、数据准备、模型部署、模型微调、评测等)提供了大量的工具,协助开发者用极低的成本构建 AI 应用,并可以持续地迭代优化效果。 LazyLLM作为商汤大装置推出的开源低代码框架,简直是AI开发者的“效率神器”

YOLOv8n机器人场景目标检测实战|第一周工作笔记1

核心完成项:基于Conda搭建Ultralytics8.0+PyTorch2.1专属环境,完成COCO2017机器人场景子集筛选(8000张,7000训+1000验),跑通YOLOv8n基础训练(epoch=50),小障碍物mAP≥65%,模型可正常输出推理结果,满足周验收全部目标。 环境说明:全程使用Conda进行包管理与环境隔离,无pip命令使用,规避版本兼容问题;模型选用YOLOv8n(轻量化版本,适配机器人端算力限制),替代原计划YOLOv9n,核心实操逻辑一致。 一、本周核心目标与执行思路 1. 核心目标 1. 掌握YOLO系列核心创新与轻量化模型适配逻辑,聚焦机器人室内小场景(室内小障碍物/桌椅/行人/台阶)检测需求; 2. 搭建稳定可复现的Ultralytics+PyTorch训练环境,规避版本冲突; 3. 筛选并整理符合YOLO格式的机器人场景自定义数据集,完成基础标注与训练集/验证集划分; 4. 跑通YOLOv8n基础训练流程,验证数据集与模型兼容性,获取基础精度、参数量、