第七章:后端API开发
序言
界面有了,数据库也准备好了。你点击"提交"按钮,数据应该存入数据库——但前端和数据库之间还缺一座桥。
这座桥就是 API(应用程序接口)。前端通过 HTTP 请求告诉后端用户想要什么,后端处理后返回响应。
什么是后端
后端是运行在服务器上的代码,负责处理前端发来的请求、与数据库交互、执行业务逻辑。
| 层 | 职责 |
|---|---|
| 前端 | 展示界面、收集用户输入、发送 HTTP 请求 |
| API | 接收请求、验证参数、调用数据库、返回响应 |
| 数据库 | 存储和检索数据 |
前端不能直接访问数据库——那样会暴露所有数据,也无法做权限控制。API 是数据库的守门员,所有数据操作必须通过它。
什么是 API Route
Route(路由) 是 Web 开发中的核心概念,指 URL 路径与处理代码之间的对应关系。用户访问某个 URL 时,路由系统决定调用哪段代码来响应。
API Route 是 Next.js 中定义 API 接口的方式。你创建一个文件,它就变成了一个可以访问的接口。
具体来说,在 app/api/ 目录下创建 route.ts 文件,就会自动生成对应的 URL 路径。比如创建 app/api/posts/route.ts,就会产生 /api/posts 这个接口。
导出处理函数
在 route.ts 文件中,你导出对应 HTTP 方法的函数。比如导出 GET 函数来处理 GET 请求,导出 POST 函数来处理 POST 请求。
Next.js 会根据请求方法自动调用对应的函数。如果同时导出了 GET 和 POST,同一个 URL 就可以同时支持获取和创建两种操作。
动态路由参数
如果路径中包含动态部分,比如 /api/posts/123 中的 123,该怎么获取呢?你在文件名中用方括号表示动态段,比如 [id],然后就可以从 params 中提取出这个 123。
版本变化快,让 AI 查文档
Next.js 版本迭代快,API 可能有变化。让 AI 用 Context7 查询最新文档,确保生成的代码符合当前版本。
RESTful 设计风格
RESTful 是一种 API 设计风格,核心思想是用 URL 表示资源,用 HTTP 方法表示操作。
比如 /api/posts 这个 URL,用 GET 方法表示获取文章列表,用 POST 方法表示创建新文章。/api/posts/123 用 GET 方法获取 id=123 的文章,用 DELETE 方法删除它。
这样设计的好处是"看到路径就知道做什么",前端开发者不用猜每个接口的用法。
参数的三种来源
后端接收参数有三种方式,需要区分清楚:
路径参数——比如 /posts/123 中的 123,嵌入在 URL 路径中,通过 params 获取(需要 await)。
查询参数——比如 /posts?page=1 中的 page=1,跟在 URL 问号后面,通过 searchParams 获取。
请求 Body——POST 请求中携带的 JSON 数据,通过 request.json() 获取。
这三种方式各有使用场景:路径参数用于标识单个资源,查询参数用于过滤或分页,Body 用于传递复杂的数据结构。
参数校验与错误处理
老师傅严肃地提醒你:永远不要信任前端发来的数据。用户可以通过浏览器开发者工具伪造任何请求,甚至直接调用 API。
你审查代码时发现,AI 生成的接口没有任何参数校验——任何人都可以传空标题、负数年龄。你让 AI 加上 Zod 库的类型安全校验,校验失败返回 400 错误。
Zod 的使用方式是:先定义一个 schema,描述数据应该长什么样(比如标题必须是字符串、长度在 1-100 之间),然后在处理请求前用这个 schema 去验证。如果验证失败,就返回 400 错误给前端。
Zod 的好处是类型安全 + 校验合一,TypeScript 类型会自动推导,不用写两遍。
错误响应格式
统一的错误响应格式让前端更容易处理。
约定一个格式:成功时返回 { success: true, data: ... },失败时返回 { success: false, error: { message: "...", code: "..." } }。
这样前端处理起来就很简单——先看 success 字段,为 true 就取 data,为 false 就显示 error.message。
连接数据库
API 的真正价值在于它是数据库的守门员。前端不能直接访问数据库,必须通过 API 作为中介。
审查时你发现几个常见问题:AI 返回了用户密码字段(安全风险)、忘记处理数据库错误导致接口崩溃、环境变量没配置导致连接失败。
正确的做法是:查询数据库前先确保环境变量配置正确;查询时用 try-catch 包裹,处理数据库错误;返回数据前过滤掉密码等敏感字段;资源不存在时返回 404,而不是让接口崩溃。
数据库操作使用 Drizzle ORM,它提供了类型安全的查询 API,可以用链式调用的方式构建查询,比如 db.query.posts.findFirst({ where: eq(posts.id, id) })。
完整 CRUD 示例
数据库操作的完整 CRUD 示例(增删改查),请让 AI 根据你的数据表结构生成。告诉它:请根据我的数据表结构,生成完整的 CRUD API 代码,使用 Drizzle ORM。
真正容易踩的坑
审查过程中,这些坑值得注意:
- 动态路由参数:
params是Promise,使用前必须 await - CORS 配置:如果前端和后端不同域,需要正确配置 CORS 头
- 缓存策略:Next.js 的
fetch默认会缓存,可能导致数据过期 - 环境变量:数据库连接字符串等敏感信息要放在
.env.local,不能提交到代码仓库 - revalidatePath:修改数据后要调用
revalidatePath清除缓存,否则前端看不到更新 - 版本差异:Next.js 版本更新快,旧教程的代码可能不适用
让 AI 反复检查
Next.js 版本迭代快,AI 训练数据可能过时。让 AI 用 Context7 查询最新文档,反复验证:检查 params 的类型、函数签名、返回值格式是否符合当前版本规范。
你的工作
整个过程中你不需要手写每个接口。你只需要告诉 AI 需求,它会生成完整的代码。你的工作是审查和验证:
- 代码能跑吗? —— 本地测试一下
- 边界情况处理了吗? —— 空值、错误、超时
- 安全吗? —— 参数校验、敏感数据过滤
- 性能行吗? —— N+1 查询、缓存策略
学会了这些,你就能放心地让 AI 帮你写后端了。
