DevToolBox免费
博客

Express.js指南:路由、中间件、REST API和身份验证

13 分钟阅读作者 DevToolBox

Express.js 完整指南:2026 年用 Node.js 构建 REST API

从零开始掌握 Express.js。本教程涵盖路由、中间件、REST API 设计、JWT 认证、错误处理,以及 Express 与 Fastify、Koa、Hapi 的对比。

TL;DR — Express.js 快速参考

Express.js 是用于构建 REST API 和 Web 应用的最小化 Node.js Web 框架。通过 npm install express 安装,用 app.get/post/put/delete 定义路由,用 app.use() 使用中间件,用四参数中间件处理错误,并使用 JWT + bcrypt 保护 API。Express 在 2026 年仍是最流行的 Node.js 框架,每周下载量超过 3000 万次。

什么是 Express.js?

Express.js 是一个快速、极简、非约束性的 Node.js Web 框架。由 TJ Holowaychuk 于 2010 年发布,现由 OpenJS 基金会维护。Express 已成为 Node.js 生态系统中构建 HTTP 服务器和 REST API 的事实标准。

该框架的设计哲学是极简主义:它只提供核心工具——路由、中间件支持和 HTTP 请求/响应工具,不强制要求任何特定的项目结构、模板引擎或数据库层。这种灵活性是 Express 最大的优势,也是它在 2026 年面对众多新框架竞争时仍保持相关性的原因。

核心要点
  • Express.js 是 Node.js http 模块之上的薄层,提供路由和中间件。
  • 中间件函数是构建模块——通过 next() 按顺序处理请求。
  • 使用 express.Router() 模块化路由,保持代码有序。
  • 始终将集中式错误处理中间件(4个参数)作为最后一个 app.use() 调用添加。
  • 使用 helmet、cors、express-rate-limit 和基于 JWT 的认证保护生产应用。
  • Fastify 比 Express 快 2–3 倍,但 Express 在生态系统规模和社区知识方面占优。

快速入门:安装与首个服务器

# 初始化新的 Node.js 项目
mkdir my-api && cd my-api
npm init -y

# 安装 Express
npm install express

# 安装 TypeScript 类型(可选但推荐)
npm install --save-dev @types/express typescript ts-node
// index.js — 最简 Express 服务器
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

app.get('/', (req, res) => {
  res.json({ message: 'Express 服务器运行正常!' });
});

app.listen(PORT, () => {
  console.log('服务器运行在 http://localhost:' + PORT);
});

路由:GET、POST、PUT、DELETE

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

// GET — 获取资源列表
router.get('/', (req, res) => {
  const { page = '1', limit = '20' } = req.query;
  res.json({ data: [], page: parseInt(page, 10), limit: parseInt(limit, 10) });
});

// POST — 创建资源
router.post('/', (req, res) => {
  const { name, email } = req.body;
  if (!name || !email) {
    return res.status(400).json({ error: '缺少必填字段' });
  }
  res.status(201).json({ id: 1, name, email });
});

// GET /:id — 获取单个资源
router.get('/:id', (req, res) => {
  res.json({ id: req.params.id });
});

// PUT /:id — 完整替换资源
router.put('/:id', (req, res) => {
  res.json({ id: req.params.id, ...req.body });
});

// DELETE /:id — 删除资源
router.delete('/:id', (req, res) => {
  res.status(204).send();
});

module.exports = router;

中间件

const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const morgan = require('morgan');
const rateLimit = require('express-rate-limit');

const app = express();

// 安全头
app.use(helmet());

// 跨域资源共享
app.use(cors({ origin: ['https://myapp.com'], credentials: true }));

// 请求日志
app.use(morgan('combined'));

// 请求体解析
app.use(express.json({ limit: '10mb' }));

// 速率限制
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 100,
  message: { error: '请求过于频繁,请稍后再试' },
});
app.use('/api/', limiter);

JWT 认证

const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');

// 注册:哈希密码
const hash = await bcrypt.hash(password, 12);

// 登录:验证并颁发 JWT
const match = await bcrypt.compare(password, user.passwordHash);
if (!match) return res.status(401).json({ error: '凭据无效' });

const token = jwt.sign(
  { sub: user.id, email: user.email },
  process.env.JWT_SECRET,
  { expiresIn: '15m' }
);
res.json({ accessToken: token });

// 认证中间件
function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: '缺少认证令牌' });
  }
  try {
    req.user = jwt.verify(authHeader.slice(7), process.env.JWT_SECRET);
    next();
  } catch (err) {
    res.status(401).json({ error: err.name === 'TokenExpiredError' ? '令牌已过期' : '令牌无效' });
  }
}

错误处理

// 集中式错误处理中间件(必须是最后一个 app.use)
function errorHandler(err, req, res, next) {
  console.error(err.message);

  if (err.isOperational) {
    return res.status(err.statusCode).json({ error: err.message, code: err.code });
  }

  res.status(500).json({
    error: process.env.NODE_ENV === 'development' ? err.message : '服务器内部错误',
  });
}

// async 错误处理包装器
function asyncHandler(fn) {
  return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
}

// 使用示例
app.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  if (!user) throw new AppError('用户不存在', 404, 'NOT_FOUND');
  res.json({ data: user });
}));

app.use(errorHandler); // 必须最后注册

常见问题

Express.js 在 2026 年还值得学习吗?

当然值得。Express 每周下载量超过 3000 万次,是 Node.js 生态中最广泛使用的框架。大量工作机会、教程和中间件都基于 Express。即使你最终使用 NestJS 或 Fastify,理解 Express 的中间件模式也至关重要,因为这些框架都建立在相同概念之上。

Express 和 Fastify 哪个更好?

Fastify 在基准测试中比 Express 快 2–3 倍,内置 JSON Schema 验证和更快的序列化。但对大多数应用来说,瓶颈在数据库而非框架。Express 生态系统更大,学习资源更丰富。建议:默认选 Express,当吞吐量成为实测瓶颈时再考虑 Fastify。

如何处理 Express 中的异步错误?

Express 4 不会自动捕获未处理的 Promise 拒绝。使用以下三种方案之一:在 try/catch 中调用 next(err);使用 asyncHandler 包装函数;或安装 express-async-errors 包。Express 5 原生支持 async/await 错误传播,无需额外处理。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON FormatterJWTJWT DecoderB→Base64 Encoder

相关文章

Node.js指南:后端开发完整教程

掌握Node.js后端开发。涵盖事件循环、Express.js、REST API、JWT认证、数据库集成、Jest测试、PM2部署和Node.js vs Deno vs Bun对比。

JavaScript Promises 和 Async/Await 完全指南

掌握 JavaScript Promises 和 async/await:创建、链式调用、Promise.all、错误处理和并发策略。

TypeScript 泛型完全指南 2026:从基础到高级模式

全面掌握 TypeScript 泛型:类型参数、约束、条件类型、映射类型、工具类型,以及事件发射器和 API 客户端等实战模式。