Skip to content

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 方法(如 getpost),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('静态资源服务启动');
});

知识回顾

  1. Express 本质:基于 http 模块封装,通过 app.listen() 启动服务器。
  2. 路由定义app.METHOD(PATH, HANDLER),支持动态路径 :id 和查询参数 ?name=xxx
  3. req/res 方法req.paramsreq.query 获取数据,res.json()res.redirect() 发送响应。
  4. 中间件核心:通过 next() 形成链式处理,可实现日志、验证、路由控制等功能。
  5. 内置中间件express.json() 解析 JSON,express.static() 提供静态文件服务。

课后练习

  1. (单选)Express 中 next() 的作用是:

    • A. 直接结束响应
    • B. 跳过当前中间件,继续后续处理
    • C. 重新启动服务器
    • D. 仅用于错误处理中间件
  2. (填空)要获取 POST 请求的 JSON 数据,需在路由前添加中间件 ______

  3. (编程)编写一个 Express 服务:

    • 监听端口 3001
    • 定义 /api/time 路由,返回当前时间的 JSON 格式。
    • 使用静态文件服务提供 public/ 文件夹中的资源。
参考答案
  1. B
  2. 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 端口');
});

扩展阅读

Built by Vitepress | Apache 2.0 Licensed