E22. Express.js 端口监听
2.1. 🌟 Express.js 基于 http 模块实现
Express 是对 Node.js 原生
http
模块的封装,提供更简洁的 API。通过对比原生代码与 Express 实现,理解其核心思想。
原生 http 模块代码
javascript
// server-http.mjs
import http from 'node:http';
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello HTTP!');
});
server.listen(3000, () => {
console.log('HTTP Server running on port 3000');
});
Express 简化代码
javascript
// server-express.mjs
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Hello Express!');
});
app.listen(3000, () => {
console.log('Express Server running on port 3000');
});
TIP
- Express 的
app
对象本质是http.Server
的封装,通过app.listen()
启动服务器。 app.get()
、app.post()
等方法自动绑定到http.Server
的路由处理逻辑。
2.2. 🌟 app 对象上的 GET/POST 方法添加监听路径
通过
app.METHOD()
定义路由,METHOD
是 HTTP 方法(如get
、post
),PATH
是 URL 路径。
基础路由示例
javascript
// routes.mjs
import express from 'express';
const app = express();
// GET 请求
app.get('/api/data', (req, res) => {
res.json({ message: 'GET 请求响应' });
});
// POST 请求
app.post('/api/data', (req, res) => {
res.send('POST 请求已接收');
});
app.listen(3000);
路径参数与查询参数
javascript
// 动态路径参数(:id)
app.get('/user/:id', (req, res) => {
res.send(`用户ID:${req.params.id}`);
});
// 查询参数(?name=xxx)
app.get('/search', (req, res) => {
res.send(`搜索关键词:${req.query.name}`);
});
2.3. 🌟 request 和 response 的核心方法
req
是请求对象,res
是响应对象,提供丰富的方法处理请求和响应。
常用 req 方法
javascript
// 示例:获取请求方法、路径、查询参数
app.get('/test', (req, res) => {
res.send(`
方法:${req.method}<br>
路径:${req.path}<br>
查询参数:${JSON.stringify(req.query)}
`);
});
常用 res 方法
javascript
// 发送不同格式的响应
app.get('/json', (req, res) => {
res.json({ status: 'success' }); // JSON 格式
});
app.get('/html', (req, res) => {
res.send('<h1>HTML 内容</h1>'); // HTML 字符串
});
app.get('/redirect', (req, res) => {
res.redirect('https://expressjs.com'); // 重定向
});
WARNING
res.send()
会自动设置Content-Type
,例如发送 JSON 时需用res.json()
。req.body
需通过express.json()
或express.urlencoded()
中间件解析。
2.4. ⭐ next 是中间件 (middleware) 的基础
中间件通过
next()
传递控制权,形成处理链。核心作用包括日志、身份验证、路由处理等。
中间件基本结构
javascript
// middleware-example.mjs
app.use((req, res, next) => {
console.log(`请求路径:${req.path}`);
next(); // 必须调用 next() 传递控制权
});
路由级中间件
javascript
// 仅对特定路由生效的中间件
app.get('/protected', (req, res, next) => {
if (req.query.token === '123') {
next(); // 继续后续处理
} else {
res.status(401).send('未授权');
}
}, (req, res) => {
res.send('受保护的资源');
});
2.5. 🌟 使用中间件支持 JSON 传输和静态文件服务
Express 提供内置中间件
express.json()
和express.static()
,简化常见功能开发。
解析 JSON 请求体
javascript
// 解析 JSON 格式的 POST 请求体
app.use(express.json());
app.post('/api/data', (req, res) => {
console.log('收到的数据:', req.body);
res.json({ received: true });
});
提供静态文件服务
javascript
// 配置静态文件目录(如 public 文件夹)
app.use(express.static('public'));
// 文件结构示例:
// public/
// index.html
// css/style.css
// img/logo.png
例:完整静态文件服务配置
javascript
import path from 'node:path';
import express from 'express';
const app = express();
const __dirname = path.resolve();
app.use(express.static(path.join(__dirname, 'public')));
app.listen(3000, () => {
console.log('静态资源服务启动');
});
知识回顾
- Express 本质:基于
http
模块封装,通过app.listen()
启动服务器。 - 路由定义:
app.METHOD(PATH, HANDLER)
,支持动态路径:id
和查询参数?name=xxx
。 - req/res 方法:
req.params
、req.query
获取数据,res.json()
、res.redirect()
发送响应。 - 中间件核心:通过
next()
形成链式处理,可实现日志、验证、路由控制等功能。 - 内置中间件:
express.json()
解析 JSON,express.static()
提供静态文件服务。
课后练习
(单选)Express 中
next()
的作用是:- A. 直接结束响应
- B. 跳过当前中间件,继续后续处理
- C. 重新启动服务器
- D. 仅用于错误处理中间件
(填空)要获取 POST 请求的 JSON 数据,需在路由前添加中间件
______
。(编程)编写一个 Express 服务:
- 监听端口
3001
。 - 定义
/api/time
路由,返回当前时间的 JSON 格式。 - 使用静态文件服务提供
public/
文件夹中的资源。
- 监听端口
参考答案
- B
express.json()
javascript
// time-server.mjs
import express from 'express';
import path from 'node:path';
const app = express();
const __dirname = path.resolve();
// 静态文件服务
app.use(express.static(path.join(__dirname, 'public')));
// 时间接口
app.get('/api/time', (req, res) => {
res.json({ time: new Date().toISOString() });
});
app.listen(3001, () => {
console.log('服务启动在 3001 端口');
});