RESTful API 设计教程 — 后端开发核心技能

适用人群:后端开发者、全栈开发者
学习时长:约1天(3-4小时)
重要程度:★★★★★(API设计是后端核心)

一、REST 是什么?

REST(Representational State Transfer)是一种API设计风格,用于构建可扩展的Web服务。

原则说明
无状态每次请求包含所有必要信息
统一接口使用标准HTTP方法
资源导向URL表示资源,HTTP方法表示操作
可缓存响应可被缓存

二、URL 设计规范

2.1 基本规则

✅ 正确
GET    /api/users           # 获取用户列表
GET    /api/users/123       # 获取单个用户
POST   /api/users           # 创建用户
PUT    /api/users/123       # 更新用户
DELETE /api/users/123       # 删除用户

❌ 错误
GET    /api/getUsers        # 不要用动词
POST   /api/createUser
GET    /api/user/delete/123

2.2 资源命名

# 使用名词复数
/api/users              # 用户列表
/api/orders             # 订单列表
/api/products           # 商品列表

# 嵌套资源(表示归属关系)
/api/users/123/orders           # 用户123的订单
/api/users/123/posts            # 用户123的文章
/api/orders/456/items           # 订单456的商品

# 避免超过2层嵌套
❌ /api/users/123/orders/456/items/789
✅ /api/items/789

2.3 查询参数

# 分页
GET /api/users?page=1&size=10

# 排序
GET /api/users?sort=created_at&order=desc

# 过滤
GET /api/users?status=active&role=admin

# 搜索
GET /api/users?keyword=张三

# 字段选择
GET /api/users?fields=id,username,email

# 组合
GET /api/users?page=1&size=10&sort=created_at&order=desc&status=active


三、HTTP 方法语义

方法语义幂等安全示例
GET获取资源GET /api/users
POST创建资源POST /api/users
PUT全量更新PUT /api/users/123
PATCH部分更新PATCH /api/users/123
DELETE删除资源DELETE /api/users/123

四、HTTP 状态码

4.1 成功响应

200 OK                  # GET成功、PUT/PATCH成功
201 Created             # POST成功,资源已创建
204 No Content          # DELETE成功,无返回内容

4.2 客户端错误

400 Bad Request         # 请求参数错误
401 Unauthorized        # 未认证(需要登录)
403 Forbidden           # 无权限(已登录但权限不足)
404 Not Found           # 资源不存在
405 Method Not Allowed  # HTTP方法不支持
409 Conflict            # 资源冲突(如用户名已存在)
422 Unprocessable Entity # 数据验证失败
429 Too Many Requests   # 请求过于频繁

4.3 服务端错误

500 Internal Server Error   # 服务器内部错误
502 Bad Gateway             # 网关错误
503 Service Unavailable     # 服务不可用


五、响应格式规范

5.1 成功响应

// GET /api/users/123
{
    "code": 200,
    "message": "success",
    "data": {
        "id": 123,
        "username": "张三",
        "email": "zhangsan@example.com",
        "created_at": "2024-01-15T10:30:00Z"
    }
}

// GET /api/users?page=1&size=10
{
    "code": 200,
    "message": "success",
    "data": {
        "items": [
            {"id": 1, "username": "张三"},
            {"id": 2, "username": "李四"}
        ],
        "pagination": {
            "page": 1,
            "size": 10,
            "total": 100,
            "total_pages": 10
        }
    }
}

// POST /api/users (创建成功)
{
    "code": 201,
    "message": "创建成功",
    "data": {
        "id": 124,
        "username": "王五"
    }
}

5.2 错误响应

// 400 参数错误
{
    "code": 400,
    "message": "参数验证失败",
    "errors": {
        "username": "用户名不能为空",
        "email": "邮箱格式不正确"
    }
}

// 401 未认证
{
    "code": 401,
    "message": "未登录或token已过期"
}

// 403 无权限
{
    "code": 403,
    "message": "无权访问该资源"
}

// 404 不存在
{
    "code": 404,
    "message": "用户不存在"
}

// 409 冲突
{
    "code": 409,
    "message": "用户名已被使用"
}

// 429 频率限制
{
    "code": 429,
    "message": "请求过于频繁,请稍后再试"
}


六、认证与授权

6.1 JWT 认证

// 登录请求
POST /api/auth/login
{
    "username": "zhangsan",
    "password": "123456"
}

// 登录响应
{
    "code": 200,
    "data": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "expires_in": 86400,
        "user": {
            "id": 123,
            "username": "张三"
        }
    }
}

// 后续请求携带Token
GET /api/users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

6.2 API Key 认证

# 方式1:请求头
GET /api/data
X-API-Key: your-api-key-here

# 方式2:查询参数
GET /api/data?api_key=your-api-key-here


七、版本控制

# 方式1:URL路径(推荐)
GET /api/v1/users
GET /api/v2/users

# 方式2:请求头
GET /api/users
Accept: application/vnd.myapp.v2+json

# 方式3:查询参数
GET /api/users?version=2


八、各语言实现示例

8.1 PHP Laravel

// routes/api.php
Route::apiResource('users', UserController::class);

// 响应
return response()->json([
    'code' => 200,
    'message' => 'success',
    'data' => $users
], 200);

// 错误响应
return response()->json([
    'code' => 422,
    'message' => '验证失败',
    'errors' => $validator->errors()
], 422);

8.2 Python Flask

from flask import jsonify

# 成功响应
@app.route('/api/users/<int:id>')
def get_user(id):
    user = User.query.get_or_404(id)
    return jsonify({
        'code': 200,
        'message': 'success',
        'data': user.to_dict()
    })

# 错误响应
@app.errorhandler(404)
def not_found(error):
    return jsonify({
        'code': 404,
        'message': '资源不存在'
    }), 404

8.3 Go Gin

// 成功响应
c.JSON(http.StatusOK, gin.H{
    "code":    200,
    "message": "success",
    "data":    user,
})

// 错误响应
c.JSON(http.StatusNotFound, gin.H{
    "code":    404,
    "message": "用户不存在",
})

8.4 Java Spring Boot

// 统一响应类
@Data
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    
    public static <T> ApiResponse<T> success(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("success");
        response.setData(data);
        return response;
    }
    
    public static ApiResponse<?> error(int code, String message) {
        ApiResponse<?> response = new ApiResponse<>();
        response.setCode(code);
        response.setMessage(message);
        return response;
    }
}

// Controller使用
@GetMapping("/api/users/{id}")
public ApiResponse<User> getUser(@PathVariable Long id) {
    return ApiResponse.success(userService.findById(id));
}


九、API 文档

9.1 Swagger/OpenAPI

openapi: 3.0.0
info:
  title: 用户管理API
  version: 1.0.0
paths:
  /api/users:
    get:
      summary: 获取用户列表
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: size
          in: query
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
    post:
      summary: 创建用户
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUser'
      responses:
        '201':
          description: 创建成功
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        username:
          type: string
        email:
          type: string


十、最佳实践清单

✅ URL使用名词复数,小写字母,连字符分隔
✅ 正确使用HTTP方法(GET/POST/PUT/DELETE)
✅ 返回合适的HTTP状态码
✅ 统一响应格式(code + message + data)
✅ 实现分页、排序、过滤
✅ 使用JWT或API Key认证
✅ API版本控制(v1, v2)
✅ 输入验证和错误处理
✅ 限流保护(429状态码)
✅ 编写API文档(Swagger)
✅ HTTPS加密传输
✅ CORS跨域配置


学习建议

  1. 先理解REST的核心原则:资源、HTTP方法、状态码
  2. 设计好URL结构,这是API的门面
  3. 统一响应格式,方便前端处理
  4. 做好错误处理,返回清晰的错误信息
  5. 编写API文档,方便团队协作
返回首页