Express框架快速上手:中间件、路由与错误处理

Express框架快速上手:中间件、路由与错误处理

预计时间:1-2 天(了解即可)


🎯 本章目标

理解 Express 的中间件机制------这是所有 Node.js Web 框架的核心原理,也是理解 NestJS 的基础。


1. Express 是什么

ini 复制代码
Express = 极简的 HTTP 请求处理框架
核心概念:路由 + 中间件 + 请求/响应对象

与 Spring MVC 对比

Spring MVC Express
@RequestMapping app.get/post/put/delete()
Filter 中间件
@RequestBody req.body
@RequestParam req.query
@PathVariable req.params
ResponseEntity res.status().json()

2. 基础使用

bash 复制代码
pnpm add express
pnpm add -D @types/express
typescript 复制代码
import express, { Request, Response, NextFunction } from 'express';

const app = express();

// 解析 JSON 请求体
app.use(express.json());

// 最基础的路由
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date() });
});

// 带参数的路由
app.get('/api/users/:id', (req, res) => {
  const { id } = req.params;      // 路径参数
  const { include } = req.query;  // 查询参数
  res.json({ id, include });
});

// POST 请求
app.post('/api/users', (req, res) => {
  const { name, email } = req.body;
  // 保存用户...
  res.status(201).json({ id: 1, name, email });
});

app.listen(3000, () => console.log('Server on port 3000'));

3. 中间件(核心概念)

中间件执行流程

scss 复制代码
请求 → [中间件1] → [中间件2] → [路由处理器] → 响应
                ↓            ↓
          next()         next()
typescript 复制代码
// 自定义中间件:请求日志
function requestLogger(req: Request, res: Response, next: NextFunction) {
  console.log(`${new Date().toISOString()} ${req.method} ${req.url}`);
  next(); // 必须调用 next() 传递控制权!
}

app.use(requestLogger); // 注册中间件

// 中间件:鉴权
function authMiddleware(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' }); // 提前返回,不调用 next()
  }
  // 验证 token...
  (req as any).user = decodedUser;
  next();
}

// 只对特定路由应用中间件
app.use('/api/protected', authMiddleware);

内置中间件

typescript 复制代码
app.use(express.json());                  // 解析 JSON body
app.use(express.urlencoded({ extended: true })); // 解析表单 body
app.use(express.static('public'));        // 静态文件服务

错误处理中间件(4个参数)

typescript 复制代码
// 错误处理中间件必须放在所有路由之后
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Internal Server Error' });
});

4. 路由组织(Router)

typescript 复制代码
import { Router } from 'express';

const userRouter = Router();

userRouter.get('/', (req, res) => { /* 列表 */ });
userRouter.get('/:id', (req, res) => { /* 详情 */ });
userRouter.post('/', (req, res) => { /* 创建 */ });
userRouter.put('/:id', (req, res) => { /* 更新 */ });
userRouter.delete('/:id', (req, res) => { /* 删除 */ });

// 挂载到主应用
app.use('/api/users', userRouter);

5. 完整项目示例

typescript 复制代码
// src/app.ts
import express from 'express';
import { userRouter } from './routes/user.routes.js';
import { errorHandler } from './middlewares/error.middleware.js';
import { requestLogger } from './middlewares/logger.middleware.js';

const app = express();

app.use(express.json());
app.use(requestLogger);

app.use('/api/users', userRouter);

app.use(errorHandler);

export default app;
typescript 复制代码
// src/index.ts
import app from './app.js';

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

6. 为什么选择 NestJS 而不是 Express

Express NestJS
架构 无约束,自由发挥 模块化,强约束
依赖注入 ❌ 手动 ✅ 内置
TypeScript 可选 原生支持
学习曲线 中等(但 Java 开发者觉得熟悉)
适合项目 小项目、快速原型 企业级应用
生态 大量第三方中间件 内置 + 官方集成包

建议:用 Express 了解中间件原理,用 NestJS 做正式项目。


下一步:NestJS入门

相关推荐
半个落月4 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
半个落月4 小时前
从 Tokenization 到 Embedding:用 Node.js 搞懂大模型为什么先“分词”再“向量化”
人工智能·node.js
小兔崽子去哪了4 小时前
Vue3 + Pinia 集成 IGV.js 实现 BAM 文件在线浏览
javascript·vue.js·后端
小月土星5 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星5 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试
还有多久拿退休金5 小时前
一个 var 让整个团队加班到凌晨——JS 闭包的那些暗坑
前端·javascript
weedsfly5 小时前
用了 React/Vue 之后,这些 DOM 操作的坑你踩过几个?
前端·javascript
Asize5 小时前
Ajax 入门:从 JSON 序列化到 XMLHttpRequest
前端·javascript·前端框架
铁皮饭盒6 小时前
@kognitivedev/rag, 用js做AI Agent开发
javascript·后端