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

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

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


今天你会学到这些关键词

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

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


上节课回顾

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

sql 复制代码
GET /       → 返回 Hello World
GET /time   → 返回当前时间

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


路由是什么?

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

bash 复制代码
用户访问的 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 表示资源

bash 复制代码
/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 - 删除结果

统一响应格式

json 复制代码
{
  "success": true,
  "data": { ... },
  "message": "操作成功"
}

用 Trae 生成代码

复制这段提示词:

markdown 复制代码
用 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 会生成类似这样的代码:

typescript 复制代码
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 适配器

typescript 复制代码
import { Elysia } from "elysia";
import { node } from "@elysiajs/node";

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

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

测试 API

启动服务:

bash 复制代码
bun run index.ts

1. 创建用户:

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

返回:

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

2. 查询所有用户:

bash 复制代码
curl http://localhost:3000/users

3. 查询单个用户:

bash 复制代码
curl http://localhost:3000/users/1

4. 删除用户:

bash 复制代码
curl -X DELETE http://localhost:3000/users/1

好 API 的 3 个标准

1. 清晰

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

bash 复制代码
✅ GET /users/orders      → 查询用户的订单
❌ GET /getUserOrderData  → 不够简洁

2. 一致

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

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

3. 可预测

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

bash 复制代码
/users      → 用户相关
/orders     → 订单相关

核心收获

今天学习了:

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


下节课预告

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

我们将:

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

思考题:

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

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

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


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

相关推荐
顾昂_1 小时前
Web 性能优化完全指南
前端·面试·性能优化
我叫黑大帅1 小时前
如何通过 Python 实现招聘平台自动投递
后端·python·面试
狼爷1 小时前
短视频播放量(Views)计数系统实现方案:高并发、不丢数的工业级实践
后端·架构
前端程序媛-Tian2 小时前
前端 AI 提效实战:从 0 到 1 打造团队专属 AI 代码评审工具
前端·人工智能·ai
支付宝体验科技2 小时前
Ant Design Pro v6.0.0 发布
前端
T畅N3 小时前
审批流设计器(前端)
前端·elementui·vue·html·流程图·js
AlunYegeer3 小时前
JAVA,以后端的视角理解前端。在全栈的路上迈出第一步。
java·开发语言·前端
苍何3 小时前
我用 Tabbit 浏览器搭了一套内容创作全自动流水线,太香了!
后端
苍何3 小时前
全网首测,TRAE SOLO 的 AI 麦克风!
后端