第五部分:第三节 - Express.js 框架入门:厨房的流程管理系统
直接使用 Node.js 的 http
模块创建复杂的 Web 应用会非常繁琐,你需要手动解析 URL、请求方法、请求头、请求体,然后根据这些信息编写大量的条件判断来决定如何处理请求和构建响应。
Express.js 是一个基于 Node.js 的极简、灵活的 Web 应用框架。它提供了一系列强大的特性,可以极大地简化 Web 服务器的开发过程。把它想象成餐厅厨房里的那套流程管理系统:它有明确的流程来接收订单、分配给不同的处理区域(路由),以及在处理过程中执行一些标准步骤(中间件)。
安装 Express:
在你的 Node.js 项目目录中(确保有 package.json
文件):
npm install express
# 或者 yarn add express
安装后,express
会出现在 package.json
的 dependencies 中。
基本使用:
创建一个文件 app.js
(或者 app.ts
如果你使用 TypeScript 并配置了编译):
// app.js
const express = require('express'); // 导入 Express 模块const app = express(); // 创建一个 Express 应用实例
const port = 3000;// 定义一个路由:当接收到 GET 请求且路径是根目录 '/' 时执行
app.get('/', (req, res) => {// req (Request) 对象包含客户端请求的信息// res (Response) 对象用于向客户端发送响应res.send('欢迎使用 Express 构建的 Web 服务器!'); // 发送文本响应
});// 定义另一个路由:当接收到 GET 请求且路径是 '/about' 时执行
app.get('/about', (req, res) => {res.send('这是一个关于页面 (Express).');
});// 启动服务器监听端口
app.listen(port, () => {console.log(`Express 应用运行在 http://localhost:${port}`);
});// 运行这个文件: node app.js
// 然后在浏览器访问 http://localhost:3000/ 和 http://localhost:3000/about
这个例子展示了 Express 的基本用法:创建应用实例,使用 app.get()
定义路由,然后在回调函数中处理请求和发送响应。
路由 (Routing):
路由决定了应用如何响应客户端对特定端点(URI)的请求以及特定的 HTTP 请求方法(GET, POST 等)。Express 提供了各种方法来处理不同的 HTTP 方法:app.get()
, app.post()
, app.put()
, app.delete()
, app.all()
(匹配所有方法) 等。
// app.js (接着上面的代码)// 处理 POST 请求到 /submit
app.post('/submit', (req, res) => {res.send('收到了 POST 请求!');
});// 匹配所有 HTTP 方法到 /api/items
app.all('/api/items', (req, res) => {res.send(`收到对 /api/items 的 ${req.method} 请求`);
});
中间件 (Middleware):
中间件是 Express 应用的核心概念。它是一个函数,可以访问请求对象 (req
)、响应对象 (res
) 和应用请求/响应循环中的下一个中间件函数 (next
)。中间件可以执行以下任务:
- 执行任何代码。
- 修改请求和响应对象。
- 结束请求-响应循环。
- 调用堆栈中的下一个中间件。
想象中间件就像在厨房处理订单流程中的一些标准步骤:比如所有订单来了都要先检查是否有特殊要求(日志中间件),或者处理所有需要烹饪的菜肴都需要先清洗食材(身份验证中间件)。
Express 中间件通常使用 app.use()
来加载。执行顺序与你调用 app.use()
的顺序有关。
// app.js (接着上面的代码)// 自定义中间件:记录所有请求的 URL
app.use((req, res, next) => {console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);next(); // 调用 next() 将请求传递给下一个中间件或路由处理程序
});// 内置中间件:用于解析 JSON 格式的请求体 (例如 POST 请求发送的 JSON 数据)
app.use(express.json());// 内置中间件:用于解析 URL-encoded 格式的请求体 (例如 HTML 表单提交的数据)
app.use(express.urlencoded({ extended: true }));// 只有在上述中间件执行之后才会执行下面的路由
app.post('/data', (req, res) => {// express.json() 中间件会把请求体解析到 req.body 中console.log("收到的请求体:", req.body);res.json({ received: true, data: req.body }); // 发送 JSON 响应
});// 注意:如果你在 app.use(myMiddleware) 之前定义路由,该中间件将不会应用于这些路由。
处理请求参数:
req.params
: 获取 URL 路径中的参数(通过路由路径中的占位符定义)。req.query
: 获取 URL 查询字符串中的参数(?key1=value1&key2=value2
)。req.body
: 获取请求体中的数据(POST, PUT 等请求)。需要上面提到的express.json()
或express.urlencoded()
等中间件来解析。
// app.js (接着上面的代码)// 路由参数: /users/123, /users/abc
app.get('/users/:userId', (req, res) => {const userId = req.params.userId; // 获取路径中的 userId 参数res.send(`获取用户 ID: ${userId}`);
});// 查询参数: /search?keyword=node&page=1
app.get('/search', (req, res) => {const keyword = req.query.keyword; // 获取查询字符串中的 keyword 参数const page = req.query.page; // 获取查询字符串中的 page 参数console.log("搜索关键词:", keyword, "页码:", page);res.send(`搜索关键词: ${keyword}, 页码: ${page}`);
});// 请求体 (需要在前面添加 app.use(express.json());)
// app.post('/data', ...) 这个例子已经展示了 req.body 的使用
小例子:包含路由和中间件的 Express 应用
// basic_express_app.js
const express = require('express');
const app = express();
const port = 3000;// 中间件:记录请求时间
app.use((req, res, next) => {req.requestTime = new Date().toISOString();next();
});// 中间件:解析 JSON 请求体
app.use(express.json());// 首页路由
app.get('/', (req, res) => {res.send(`收到请求于: ${req.requestTime}`);
});// 用户详情路由,带路由参数
app.get('/user/:name', (req, res) => {const userName = req.params.name;res.send(`用户: ${userName}, 请求时间: ${req.requestTime}`);
});// 接收 JSON 数据的 POST 路由
app.post('/api/submit-data', (req, res) => {console.log("收到的数据:", req.body);res.json({status: 'success',receivedData: req.body,requestTime: req.requestTime});
});// 启动服务器
app.listen(port, () => {console.log(`应用运行在 http://localhost:${port}`);
});// 运行: node basic_express_app.js
// 测试:
// GET http://localhost:3000/
// GET http://localhost:3000/user/alice
// POST http://localhost:3000/api/submit-data (使用工具发送 JSON 数据,如 {"message": "hello"})
小结: Express.js 是构建 Node.js Web 应用的强大框架,它简化了路由管理和请求处理。中间件是 Express 的核心,提供了在请求-响应流程中插入自定义逻辑的能力。通过 req.params
, req.query
, req.body
可以方便地获取客户端发送的参数。
练习:
- 创建一个新的 Express 项目。
- 安装 Express。
- 创建一个
app.js
文件,创建一个 Express 应用实例并监听端口。 - 添加一个中间件,用于记录所有请求的方法和路径到控制台。
- 添加一个 GET 路由
/greet
,接收一个查询参数name
,如果提供了name
,则返回你好,[name]!
,否则返回你好!
。 - 添加一个 POST 路由
/echo
,接收一个 JSON 请求体,将接收到的 JSON 数据原样返回给客户端。确保使用了正确的中间件来解析请求体。