Skip to content

第七章:后端API开发

img

序言

界面有了,数据库也准备好了。你点击"提交"按钮,数据应该存入数据库——但前端和数据库之间还缺一座桥。

这座桥就是 API(应用程序接口)。前端通过 HTTP 请求告诉后端用户想要什么,后端处理后返回响应。


什么是后端

你试着在前端直接连数据库,但老师傅拦住了你——"前端代码运行在用户的浏览器里,如果前端直接连数据库,用户打开 F12 就能看到你的数据库密码,还能随意删除别人的数据。" 你才意识到,前端和数据库之间必须有一个"中间人"来把关。

后端是运行在服务器上的代码,负责处理前端发来的请求、与数据库交互、执行业务逻辑。

职责
前端展示界面、收集用户输入、发送 HTTP 请求
API接收请求、验证参数、调用数据库、返回响应
数据库存储和检索数据

前端不能直接访问数据库——那样会暴露所有数据,也无法做权限控制。API 是数据库的守门员,所有数据操作必须通过它。


什么是 API Route

你理解了需要后端,但具体怎么写?难道要自己搭一个 Express 服务器?老师傅说不用——Next.js 内置了 API Route 功能,创建一个文件就是一个接口,不需要额外搭建服务器。

不过在讲 API Route 之前,先理解一个更基础的概念:路由(Route)

路由:URL 决定你看到什么

你每天都在跟路由打交道,只是没意识到。打开浏览器看看地址栏:

  • 访问 movie.douban.com/ → 看到豆瓣电影首页
  • 访问 movie.douban.com/subject/37311135/ → 看到《飞驰人生 3》的详情页
  • 访问 movie.douban.com/subject/37311135/comments?status=P → 看到这部电影的短评(?status=P 表示"看过的人的评论")
  • 访问 movie.douban.com/chart → 看到排行榜

URL 不同,看到的页面就不同。路由就是这件事——URL 路径决定了展示什么内容。 ? 后面的部分是查询参数,用来进一步筛选或控制显示方式。

在 Next.js 里,这个对应关系直接体现在文件结构上:

app/
├── page.tsx                    → yourdomain.com/
├── subject/
│   └── [id]/
│       ├── page.tsx            → yourdomain.com/subject/37311135
│       └── comments/
│           └── page.tsx        → yourdomain.com/subject/37311135/comments
└── chart/
    └── page.tsx                → yourdomain.com/chart

文件夹结构就是 URL 结构。创建一个文件,就多了一个页面。[id] 是动态段——不管是 37311135 还是别的电影 ID,都由同一个 page.tsx 处理。这就是 Next.js 的文件系统路由——不需要写配置文件来定义"哪个 URL 对应哪个页面",文件放在哪,URL 就是什么。

从页面路由到 API 路由

上面的路由是给用户看页面的。API Route 是同样的思路,但不是返回页面,而是返回数据。

app/api/ 目录下创建 route.ts 文件,就会生成一个数据接口:

  • app/api/movies/route.tsyourdomain.com/api/movies(返回电影列表的 JSON 数据)
  • app/api/movies/[id]/route.tsyourdomain.com/api/movies/123(返回某部电影的 JSON 数据)

区别只是:page.tsx 返回用户看到的页面,route.ts 返回程序用的数据。

导出处理函数

route.ts 文件中,你导出对应 HTTP 方法的函数。比如导出 GET 函数来处理 GET 请求,导出 POST 函数来处理 POST 请求。

Next.js 会根据请求方法自动调用对应的函数。如果同时导出了 GETPOST,同一个 URL 就可以同时支持获取和创建两种操作。

版本变化快,让 AI 查文档

Next.js 版本迭代快,API 可能有变化。让 AI 用 Context7 查询最新文档,确保生成的代码符合当前版本。


跟 AI 聊后端之前,先认识几个关键词

在 7.0 动手之前,有几个词你会反复碰到。不用背,混个脸熟就行——后面每一节都会在具体场景里再遇到它们。

RESTful——API 的命名规范。核心思想是用 URL 表示资源,用 HTTP 方法表示操作。其实你每天都在发 HTTP 请求——在浏览器地址栏输入网址按回车,就是一个 GET 请求;填完注册表单点提交,就是一个 POST 请求。RESTful 就是把这套方法用得更规范:GET /api/movies 获取电影列表,POST /api/movies 创建新电影,DELETE /api/movies/123 删除 id=123 的电影。看到路径就知道做什么。跟 AI 说一句"用 RESTful 风格",它就会自动按这套规范来。

GET
读取 (Read)
POST
创建 (Create)
PATCH
更新 (Update)
DELETE
删除 (Delete)

参数的三种来源——你在浏览器地址栏里其实已经见过前两种了:

  • 路径参数movie.douban.com/subject/37311135 中的 37311135 就是路径参数,标识"我要看哪部电影"
  • 查询参数movie.douban.com/subject/37311135/comments?status=P? 后面的部分,告诉后端"只看'看过'的人的评论"
  • 请求 Body:这个在地址栏里看不到——当你填完表单点"提交"时,表单里的数据(标题、年份、简介)会打包成 JSON 放在请求体里发给后端

路径参数标识"哪个资源",查询参数控制"怎么查",Body 传递"要创建或修改的数据"。

GET/api/posts?page=1
查询参数 searchParams: page=1
此请求没有请求体和路径参数,仅通过查询参数筛选数据

统一响应格式——在项目初期就跟 AI 约定:成功返回 { success: true, data: ... },失败返回 { success: false, error: { message: "..." } }。这样前端处理起来一致且简单——先看 success 字段,为 true 就取 data,为 false 就显示错误信息。

API 不只有 REST 一种风格

本章讲的都是 RESTful API——用 URL 表示资源、用 HTTP 方法表示操作。这是最主流的方式,也是你最先会接触到的。

但你可能会遇到 AI 生成的代码里没有 route.ts 文件、没有 GET /api/movies 这样的 URL,取而代之的是类似 trpc.movie.list() 这样的函数调用。这说明 AI 用了 tRPC——一种让前端像调用本地函数一样调用后端接口的方案。它的好处是前后端类型自动同步,改了后端接口签名,前端立刻报类型错误,不会出现"后端改了字段名前端不知道"的问题。

你不需要指定用哪种方式。如果你跟 AI 说"用 RESTful 风格",它就用 REST。如果你不指定,AI 会根据项目情况选择——看到 tRPC 出现在代码里不用觉得奇怪,它和 REST 只是风格不同,解决的是同一个问题:让前端和后端能通信。


你的工作

整个过程中你不需要手写每个接口。你只需要告诉 AI 需求,它会生成完整的代码。你的工作是验证结果

  1. 跑起来了吗? —— pnpm dev 启动,页面能正常操作
  2. 数据库对吗? —— 打开 Drizzle Studio,看数据是否正确写入
  3. 报错了吗? —— 把终端里的报错整段复制给 AI,让它修

不需要读懂每一行代码。知道每个文件的职责,出问题时能告诉 AI "改哪个文件"就够了。


本章小节

小节内容
7.0 跑通你的第一个全栈应用动手做一个 Todo 应用,体验完整的全栈数据流
7.1 一个接口不够用了关联查询、分页、过滤排序——当数据量和需求增长时怎么办
7.2 当接口出了问题参数校验、幂等性、错误处理——上线后的第一批坑
7.3 让接口更好用版本管理、接口文档、批量操作——把接口当产品来打磨