成为AI全栈 - 第3课:路由 RESTful Elysia 状态码 设计规范

27 阅读5分钟

成为AI全栈 - 第3课:路由 RESTful Elysia 状态码 设计规范

从今天开始, 你是架构师,学会关键词就行,代码让AI实现😁


今天你会学到这些关键词

关键词一句话解释
路由URL 到功能的映射,如 /users → 查询用户
RESTfulAPI 设计规范,用 HTTP 方法表示操作
Elysia高性能 Web 框架,链式 API 设计
状态码HTTP 响应状态,如 200 成功、404 找不到

一句话总结:用 Elysia 设计 RESTful 路由,让 API 清晰、一致、可预测。


上节课回顾

我们用 AI 生成了一个简单的后端服务:

GET /       → 返回 Hello World
GET /time   → 返回当前时间

今天我们要深入理解:路由


路由是什么?

一句话:路由就是 URL 到功能的映射。

用户访问的 URL     →     后端执行的功能
─────────────────────────────────────────
GET /users              →  查询所有用户
GET /users/123          →  查询 ID 为 123 的用户
POST /users             →  创建新用户
PUT /users/123          →  更新 ID 为 123 的用户
DELETE /users/123       →  删除 ID 为 123 的用户

RESTful API 设计规范

RESTful 是一种 API 设计规范,让接口更清晰、统一。

核心原则

1. 用 URL 表示资源

/users          → 用户资源
/orders         → 订单资源
/products       → 商品资源

注意, 所有资源都用复数命名

2. 用 HTTP 方法表示操作

方法操作示例
GET查询GET /users 查询所有用户
POST创建POST /users 创建用户
PUT更新(全部)PUT /users/123 更新用户123
PATCH更新(部分)PATCH /users/123 部分更新
DELETE删除DELETE /users/123 删除用户123
注意, 大部分编辑功能我们都应该用PATCH方法而不是PUT

3. 用状态码表示结果

状态码含义场景
200成功请求正常处理
201创建成功新建资源成功
400请求错误参数不对
401未授权需要登录
404找不到资源不存在
500服务器错误后端出错了

实战:设计用户管理 API

我们要设计一套用户管理的 API,包含增删改查。

API 设计表

功能方法URL请求体响应
查询所有用户GET/users-用户列表
查询单个用户GET/users/:id-单个用户
创建用户POST/users{name, email}新用户
更新用户PUT/users/:id{name, email}更新后的用户
删除用户DELETE/users/:id-删除结果

统一响应格式

{
  "success": true,
  "data": { ... },
  "message": "操作成功"
}

用 Trae 生成代码

复制这段提示词:

用 Elysia 框架创建用户管理 RESTful API

要求:
1. 内存存储(用 Map 或数组模拟数据库)
2. 实现以下接口:
   - GET /users - 查询所有用户
   - GET /users/:id - 查询单个用户
   - POST /users - 创建用户(body: {name, email})
   - PUT /users/:id - 更新用户
   - DELETE /users/:id - 删除用户

3. 统一响应格式:
   { success: boolean, data: any, message: string }

4. 状态码规范:
   - 200: 成功
   - 201: 创建成功
   - 404: 用户不存在
   - 400: 参数错误

5. 添加请求日志

请生成完整的 TypeScript 代码

Trae 会生成类似这样的代码:

import { Elysia } from "elysia";

// 内存存储
const users = new Map();
let idCounter = 1;

const app = new Elysia()
  .onRequest(({ request }) => {
    console.log(`${request.method} ${new URL(request.url).pathname}`);
  })
  
  // 查询所有用户
  .get("/users", () => {
    return {
      success: true,
      data: Array.from(users.values()),
      message: "查询成功"
    };
  })
  
  // 查询单个用户
  .get("/users/:id", ({ params: { id }, set }) => {
    const user = users.get(id);
    
    if (!user) {
      set.status = 404;
      return { success: false, data: null, message: "用户不存在" };
    }
    
    return { success: true, data: user, message: "查询成功" };
  })
  
  // 创建用户
  .post("/users", async ({ body, set }) => {
    const { name, email } = body as { name: string; email: string };
    
    if (!name || !email) {
      set.status = 400;
      return { success: false, data: null, message: "name 和 email 不能为空" };
    }
    
    const newUser = {
      id: String(idCounter++),
      name,
      email,
      createdAt: new Date().toISOString()
    };
    
    users.set(newUser.id, newUser);
    
    set.status = 201;
    return { success: true, data: newUser, message: "创建成功" };
  })
  
  // 更新用户
  .put("/users/:id", async ({ params: { id }, body, set }) => {
    const user = users.get(id);
    
    if (!user) {
      set.status = 404;
      return { success: false, data: null, message: "用户不存在" };
    }
    
    const { name, email } = body as { name?: string; email?: string };
    
    const updatedUser = {
      ...user,
      ...(name && { name }),
      ...(email && { email }),
      updatedAt: new Date().toISOString()
    };
    
    users.set(id, updatedUser);
    
    return { success: true, data: updatedUser, message: "更新成功" };
  })
  
  // 删除用户
  .delete("/users/:id", ({ params: { id }, set }) => {
    const user = users.get(id);
    
    if (!user) {
      set.status = 404;
      return { success: false, data: null, message: "用户不存在" };
    }
    
    users.delete(id);
    
    return { success: true, data: null, message: "删除成功" };
  })
  
  .listen(3000);

console.log(`Server running at http://localhost:${app.server?.port}`);

💡 Node.js 用户注意:需要修改代码使用 Node 适配器

import { Elysia } from "elysia";
import { node } from "@elysiajs/node";

// ... 路由代码 ...

.listen(3000, node);  // ← 加上 node 适配器

测试 API

启动服务:

bun run index.ts

1. 创建用户:

curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name": "张三", "email": "zhangsan@example.com"}'

返回:

{
  "success": true,
  "data": {
    "id": "1",
    "name": "张三",
    "email": "zhangsan@example.com",
    "createdAt": "2024-01-15T10:30:00.000Z"
  },
  "message": "创建成功"
}

2. 查询所有用户:

curl http://localhost:3000/users

3. 查询单个用户:

curl http://localhost:3000/users/1

4. 删除用户:

curl -X DELETE http://localhost:3000/users/1

好 API 的 3 个标准

1. 清晰

URL 一看就知道是做什么的:

✅ GET /users/orders      → 查询用户的订单
❌ GET /getUserOrderData  → 不够简洁

2. 一致

同样的场景用同样的格式:

✅ 所有列表接口都返回 { success, data: [], message }
✅ 所有错误都返回 4xx/5xx 状态码

3. 可预测

符合 RESTful 规范,前端一看就懂:

/users      → 用户相关
/orders     → 订单相关

核心收获

今天学习了:

路由 = URL 到功能的映射 ✅ RESTful 规范 = 用 HTTP 方法表示操作 ✅ 状态码 = 表示请求结果 ✅ 统一响应格式 = 让前端好处理


下节课预告

第4课:不用懂 SQL,AI 帮你操作数据库

我们将:

  • 理解数据库和 ORM
  • 用 Drizzle ORM 操作 SQLite
  • 把内存存储换成真正的数据库

思考题:

如果要设计一个文章管理 API,你会怎么设计路由?

提示:文章有标题、内容、作者、发布时间。

欢迎在评论区分享你的设计。


如果觉得有帮助,欢迎点赞、在看、转发。