Express 框架入门:路由、中间件与静态文件

FreeGuideOnline 最新 2026-06-15

什么是 Express?

Express 是一个基于 Node.js 平台的极简、灵活的 Web 应用开发框架。它对 Node.js 的原生 HTTP 模块进行了高度封装,提供了一套简洁的 API,让你能够快速、优雅地构建 Web 应用程序和 API。本教程将带你掌握 Express 最核心的三大概念:路由、中间件与静态文件服务。

环境准备与安装

在开始之前,请确保你的系统已经安装了 Node.js(建议版本 14 及以上)。可以通过终端执行以下命令检查版本:

node -v
npm -v

创建项目目录并初始化:

mkdir my-express-app
cd my-express-app
npm init -y

安装 Express:

npm install express

第一个 Express 应用

在项目根目录下创建 app.js 文件,写入以下代码:

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

运行 node app.js,在浏览器访问 http://localhost:3000,即可看到输出。下面我们深入路由、中间件和静态文件。

路由基础

路由决定了应用如何响应客户端对特定端点的请求。一个路由由一个 HTTP 方法、一个路径和一个处理函数构成。

基本路由

app.get('/hello', (req, res) => {
  res.send('GET 请求到达 /hello');
});

app.post('/user', (req, res) => {
  res.send('POST 请求创建用户');
});

app.put('/user/:id', (req, res) => {
  res.send(`PUT 请求更新用户 ${req.params.id}`);
});

app.delete('/user/:id', (req, res) => {
  res.send(`DELETE 请求删除用户 ${req.params.id}`);
});

路由参数与查询字符串

通过路径参数(:参数名)可以捕获 URL 中的动态值:

app.get('/products/:category/:id', (req, res) => {
  const { category, id } = req.params;
  res.send(`分类:${category},产品ID:${id}`);
});

访问 http://localhost:3000/products/electronics/123 将看到对应的输出。

查询字符串可以通过 req.query 获取:

app.get('/search', (req, res) => {
  const { q, page } = req.query;
  res.send(`搜索关键词:${q},页码:${page}`);
});

使用 express.Router 组织路由

当路由越来越多时,建议将其拆分为独立的路由模块。创建 routes/users.js

const express = require('express');
const router = express.Router();

// 该路由挂载在 /users 下
router.get('/', (req, res) => {
  res.send('用户列表');
});

router.get('/:id', (req, res) => {
  res.send(`用户详情:${req.params.id}`);
});

module.exports = router;

app.js 中挂载:

const usersRouter = require('./routes/users');
app.use('/users', usersRouter);

中间件详解

中间件是 Express 最强大的特性之一。它是一个函数,可以访问请求对象(req)、响应对象(res)以及应用程序请求-响应循环中的下一个中间件函数(next)。

中间件执行顺序

Express 中间件按照代码定义的顺序依次执行。一个中间件可以执行任何代码、修改请求和响应对象、结束请求-响应循环,或者调用 next() 将控制权交给下一个中间件。

app.use((req, res, next) => {
  console.log('第一个中间件');
  next();
});

app.use((req, res, next) => {
  console.log('第二个中间件');
  res.send('中间件链结束');
});

内置中间件

Express 内置了几个常用的中间件函数。

  • express.json():用于解析 JSON 格式的请求体。
  • express.urlencoded({ extended: false }):用于解析 URL 编码的请求体(如表单提交)。
  • express.static():提供静态文件服务(下一节详解)。
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

这样配置后,req.body 就能正确获取客户端发送的数据了。

自定义中间件

你可以编写自己的中间件来实现日志记录、权限验证等功能。

const loggerMiddleware = (req, res, next) => {
  const timestamp = new Date().toISOString();
  console.log(`[${timestamp}] ${req.method} ${req.url}`);
  next();
};

app.use(loggerMiddleware);

应用级中间件挂载在 app 上,也可以针对特定路由生效:

app.use('/admin', (req, res, next) => {
  // 模拟权限检查
  if (!req.headers.authorization) {
    return res.status(403).send('未授权');
  }
  next();
});

错误处理中间件

错误处理中间件需要四个参数:(err, req, res, next)。它必须放在所有中间件和路由之后定义。

app.get('/error', (req, res) => {
  throw new Error('故意抛出的错误');
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('服务器内部错误!');
});

静态文件服务

Web 应用通常需要直接提供 HTML、CSS、JavaScript、图片等静态文件。Express 内置的 express.static 中间件让这一任务变得极其简单。

基本用法

假设将静态文件放在项目根目录下的 public 文件夹中:

my-express-app/
├── public/
│   ├── index.html
│   ├── style.css
│   └── images/
│       └── logo.png
└── app.js

app.js 中添加:

app.use(express.static('public'));

现在,直接访问 http://localhost:3000/index.htmlhttp://localhost:3000/images/logo.png 即可获取对应文件。

虚拟路径前缀

有时我们希望静态文件挂载在一个虚拟路径下,例如所有静态资源都以 /static 开头访问:

app.use('/static', express.static('public'));

此时访问路径变为 http://localhost:3000/static/style.css

多个静态目录

可以多次调用 express.static 来设置多个静态目录,Express 会按注册顺序查找文件。

app.use(express.static('public'));
app.use(express.static('uploads'));

配置选项

express.static 可以接受第二个参数来配置行为,例如设置缓存或索引文件:

app.use(express.static('public', {
  maxAge: '1d',        // 缓存一天
  index: false,        // 禁用目录索引
  extensions: ['html'] // 当请求缺少扩展名时自动补全
}));

综合示例:构建一个简易 API 骨架

结合上述知识,我们来创建一个返回 JSON 数据的简易图书 API,同时为前端页面提供静态文件服务。

目录结构:

my-book-api/
├── public/
│   └── index.html
├── routes/
│   └── books.js
└── app.js

app.js

const express = require('express');
const app = express();
const port = 3000;

// 内置中间件
app.use(express.json());
app.use(express.static('public'));

// 自定义日志中间件
app.use((req, res, next) => {
  console.log(`${new Date().toLocaleTimeString()} - ${req.method} ${req.path}`);
  next();
});

// 路由模块
const booksRouter = require('./routes/books');
app.use('/api/books', booksRouter);

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.message);
  res.status(500).json({ error: '服务器内部错误' });
});

app.listen(port, () => {
  console.log(`服务已启动,访问 http://localhost:${port}`);
});

routes/books.js

const express = require('express');
const router = express.Router();

let books = [
  { id: 1, title: 'Express入门', author: '张三' },
  { id: 2, title: 'Node.js实战', author: '李四' }
];

// 获取所有图书
router.get('/', (req, res) => {
  res.json(books);
});

// 获取单本图书
router.get('/:id', (req, res) => {
  const book = books.find(b => b.id === parseInt(req.params.id));
  if (!book) return res.status(404).json({ error: '未找到该图书' });
  res.json(book);
});

// 新增图书
router.post('/', (req, res) => {
  const { title, author } = req.body;
  if (!title || !author) {
    return res.status(400).json({ error: '标题和作者不能为空' });
  }
  const newBook = {
    id: books.length + 1,
    title,
    author
  };
  books.push(newBook);
  res.status(201).json(newBook);
});

module.exports = router;

此时,你可以通过 http://localhost:3000/api/books 测试 API,并且在 public/index.html 中编写前端界面来消费这些接口。

总结

通过本教程,你已经掌握了 Express 框架的三大基石:

  • 路由:定义应用端点,处理不同 HTTP 方法,组织模块化路由。
  • 中间件:串联请求处理流程,实现日志、解析、鉴权等功能,并正确处理错误。
  • 静态文件服务:轻松托管前端资源,支持虚拟路径和灵活配置。

Express 的生态系统极其丰富,接下来你可以继续学习模板引擎(如 EJS、Pug)、数据库集成(MongoDB/Mongoose、MySQL)以及部署相关的知识。开始构建你自己的 Web 应用吧!