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

14 阅读1分钟

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

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


🎯 本章目标

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


1. Express 是什么

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

与 Spring MVC 对比

Spring MVCExpress
@RequestMappingapp.get/post/put/delete()
Filter中间件
@RequestBodyreq.body
@RequestParamreq.query
@PathVariablereq.params
ResponseEntityres.status().json()

2. 基础使用

pnpm add express
pnpm add -D @types/express
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. 中间件(核心概念)

中间件执行流程

请求 → [中间件1][中间件2][路由处理器] → 响应
                ↓            ↓
          next()         next()
// 自定义中间件:请求日志
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);

内置中间件

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

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

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

4. 路由组织(Router)

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. 完整项目示例

// 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;
// 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

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

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


下一步:NestJS入门