1. 创建服务器并启动服务
项目里 Express 应用在 index.js 中创建并监听端口;src/todo.js 引入该实例后注册业务路由。
import express from "express";
// const express = require("express"); // CommonJS 写法
const app = express();
// 解析 JSON 请求体
app.use(express.json());
// 解析 x-www-form-urlencoded 表单
app.use(express.urlencoded({ extended: true }));
const PORT = 8080;
app.get("/health", (req, res) => {
res.json({
status: "ok",
message: "API is running",
});
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
export default app;
核心说明:
注册路由
app.get("/health", handler);
访问:
http://localhost:8080/health
时会执行对应的处理函数(handler)。
返回 JSON
res.json(obj);
Express 会自动设置响应头:
Content-Type: application/json
例如:
res.json({
status: "ok",
});
返回:
{
"status": "ok"
}
导出应用实例
export default app;
这样其他模块(例如 src/todo.js)就可以导入同一个 Express 实例,并继续挂载业务路由。
2. npm 脚本与热更新
在 package.json 的 scripts 中给常用命令起别名:
{
"dev": "node --watch ./src/todo.js",
"start": "node ./src/todo.js",
"stop": "powershell -Command \"Get-Process node -ErrorAction SilentlyContinue | Stop-Process -Force\""
}
常用命令
| 命令 | 作用 |
|---|---|
npm run dev |
开发模式,文件变更后自动重启(Node 20+ 的 --watch) |
npm start |
普通启动,部署时常用 |
npm run stop |
强制结束本机所有 node 进程(Windows PowerShell) |
dev 命令拆解
node --watch ./src/todo.js
| 部分 | 含义 |
|---|---|
node |
用 Node.js 运行脚本 |
--watch |
监听依赖文件变化,保存后终端出现 Restarting,无需手动重启 |
./src/todo.js |
入口文件;会先加载 index.js 启动服务,再注册 Todo 路由 |
3. header、req 与 res
HTTP 有很多 Header,常见例如:
| Header | 作用 |
|---|---|
Content-Type |
Body 是什么格式(JSON、表单等) |
Authorization |
带 token(后面鉴权会用) |
Accept |
客户端希望收到什么格式 |
Cookie |
浏览器带的 cookie |
Express 中每个请求处理函数都会收到两个重要参数:
(req, res)
| 参数 | 含义 | 常见用法 |
|---|---|---|
req(request) |
客户端发来的请求 | req.query 查询参数、req.params 路径参数、req.body 请求体 |
res(response) |
返回给客户端的响应 | res.json()、res.status(404).json()、res.send() |
req 常见数据来源
查询参数(Query)
请求:
GET /todo?id=1
获取:
req.query.id
路径参数(Params)
请求:
GET /todo/1
路由:
app.get("/todo/:id", ...)
获取:
req.params.id
请求体(Body)
请求:
{
"title": "学习 Node"
}
获取:
req.body.title
4. 启用 ES Module(import / export)
在 package.json 中添加:
{
"type": "module"
}
之后即可使用:
import xxx from "xxx";
export default xxx;
而不再默认使用:
const xxx = require("xxx");
module.exports = xxx;
5. Postman Body 类型对照
调试接口时,经常需要给请求添加 Body。
Postman 提供了多种格式。
| 类型 | Content-Type | 含义 | 典型场景 |
|---|---|---|---|
| none | --- | 不发 Body | 只需 URL / Header,如登出接口 |
| form-data | multipart/form-data |
多字段,可含文件 | 头像上传、带附件的表单 |
| x-www-form-urlencoded | application/x-www-form-urlencoded |
key=value&key2=value2 |
传统 HTML 表单、部分 OAuth 接口 |
| raw(JSON) | application/json |
原始文本,常用 JSON | 现代 REST API(最常用) |
| binary | 视文件而定 | Body 为单个二进制文件 | 直接上传 PDF、图片等 |
| GraphQL | --- | GraphQL 专用格式 | 后端为 GraphQL 时使用 |
raw + JSON 示例
请求体:
{
"title": "学习 Postman",
"completed": false
}
Postman 选择:
Body
└── raw
└── JSON
时,一般会自动添加:
Content-Type: application/json
后端需要配合:
app.use(express.json());
才能正确解析请求体。
express.json() 只做一件事:把请求 Body 里的 JSON 字符串解析成 JavaScript 对象,挂到 req.body 上。
| 数据来源 | Express 怎么拿到 | 要不要 express.json() |
|---|---|---|
路径参数 :id |
自动 → req.params |
不需要 |
查询参数 ?page=1 |
自动 → req.query |
不需要 |
| Body 里的 JSON | 需要中间件 → req.body |
需要 |
x-www-form-urlencoded 示例
html
<!DOCTYPE html>
<html>
<body>
<form action="https://api.example.com/todos" method="POST">
<input type="text" name="title" value="学习Node" />
<input type="checkbox" name="done" value="true" />
<button type="submit">提交</button>
</form>
</body>
</html>
点击「提交」后发出的 HTTP 请求
用户点击「提交」后,浏览器会发送类似下面的 HTTP 请求:
POST /todos HTTP/1.1
Host: api.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 23
title=学习Node&done=true
要点
| 项目 | 说明 |
|---|---|
| URL | 只有路径 /todos,没有 ?title=... |
| Body | 数据在请求体中:title=学习Node&done=true |
| 格式 | 与 query string 相同,只是位置不同(放在 body 里) |
对比说明
-
Query String(GET):参数在 URL 中
GET /todos?title=学习Node&done=true -
Form Body(POST):参数在请求体中
POST /todos+ body:title=学习Node&done=true
两种方式的参数编码格式一致(key=value&key=value),区别在于参数所在位置:URL 查询字符串 vs 请求体。
6、POST 请求的完整链路
| 步骤 | 阶段 | 执行位置 | 输入 / 触发 | 处理动作 | 输出 / 结果 |
|---|---|---|---|---|---|
| ① | 客户端发起请求 | Postman / 前端 fetch |
用户提交待办 | POST http://localhost:8080/api/todos Header: Content-Type: application/json Body: {"title":"学习中间件"} |
HTTP 请求报文发出(Body 此时为原始字符串) |
| ② | 服务端接收 | Node.js + Express | TCP 连接建立 | Express 监听端口,接收 HTTP 请求 | 进入 Express 应用,开始中间件链 |
| ③ | 中间件链 | index.js(按注册顺序) |
原始请求体流 | express.json() 读取 Body 流 → JSON.parse() → 挂载到 req.body |
req.body = { title: "学习中间件" } (表单则用 urlencoded 中间件解析) |
| ④ | 路由匹配 | index.js 路由层 |
req.method === POST req.path === /api/todos |
匹配 app.post("/api/todos", ...) |
命中对应路由处理器 |
| ⑤ | 业务逻辑 | todo.js |
req.body.title |
取出 title → 生成 newTodo → push 进 todos 数组 |
内存中新增一条待办记录 |
| ⑥ | 响应返回 | todo.js 路由处理器 |
newTodo 对象 |
res.status(201).json(newTodo) |
HTTP 201 Created + JSON Body 返回客户端 |