Node.js + Express 入门实战笔记-02-中间件详解
2026/6/18 22:10:50 网站建设 项目流程

Express 中间件与 Router 完整解析

一、应用级全局中间件

app.use():注册应用级中间件。

路由模块(Router)、express.json()(req, res, next) => {},在 Express 眼里都是中间件。

// 挂载 todo 路由模块 app.use("/api/todos", todoRouter);

含义是:把todoRouter挂到/api/todos下;请求进来时先匹配路径前缀,再交给 router 里的路由。


二、app.use 怎么区分参数?

Express 的规则很简单:

app.use([path,] ...middleware)
// 伪代码,表达 Express 的解析逻辑 app.use = function (...args) { let path = "/"; // 默认:匹配所有路径 let middlewares = args; if (typeof args[0] === "string" || isPathPattern(args[0])) { path = args[0]; // 第一个是路径 middlewares = args.slice(1); // 后面才是中间件 } else if (typeof args[0] === "function") { // 第一个是函数 → 没有写路径,用默认 "/" path = "/"; middlewares = args; } // 把 middlewares 注册到 path 上 };
参数是什么
字符串 / 正则 / 数组挂载路径(mount path)
函数中间件(含 Router、错误处理中间件)

Router 本质上也是函数,签名是:

(req, res, next) => void

所以能传给app.use()


三、常见用法

1. 只传一个函数 —— 全局中间件

app.use((req, res, next) => { console.log("请求来了"); next(); });

所有请求都会经过,没有路径限制。

index.js第 8 行就是这种。


2. 只传一个「内置中间件函数」

app.use(express.json()); app.use(express.urlencoded({ extended: true }));

同样是全局中间件,express.json()返回的就是一个:

(req, res, next) => {}

3. 路径 + 路由中间件

app.use("/api/todos", todoRouter);

只有 URL 以/api/todos开头才会进入todoRouter


4. 路径 + 多个中间件(可链式写)

app.use("/api", authMiddleware, logMiddleware, someRouter);

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

app.use((error, req, res, next) => { res.status(500).json({ error: error.message }); });

Express 靠参数个数是 4 个来识别错误中间件。


6. 只传 Router,不写路径

app.use(todoRouter); // 等价于挂载在 "/"

一共多少种?

如果按「语法形式」数,常见就 6 类:

  1. 只传函数

  2. 只传内置中间件

  3. 路径 + Router

  4. 路径 + 多个中间件

  5. 错误处理中间件

  6. 只传 Router

如果按「本质」数,其实就 2 种:

  1. 普通中间件

  2. 错误处理中间件

Router、express.json()、404 兜底,都属于普通中间件,只是职责不同。


四、app.get 和 router.get 的区别

两者语法一样,差别在「注册在哪、路径怎么算」。

app.getrouter.get
注册对象主应用 app子路由 router
路径完整路径,如/health相对路径,相对挂载点
匹配方法只匹配 GET只匹配 GET
典型用途少量独立路由一组相关路由拆到单独文件

小结

app.use没有「路由模块」这个特殊类型——Router 就是中间件,只是里面又注册了router.get/post/...

区分参数:

  • 第一个是路径(可选)

  • 后面全是中间件函数(可多个)

app.getvsrouter.get

  • app.get写绝对路径

  • router.get写相对路径

  • app.use(prefix, router)拼成完整 URL


五、router.use 详解

router.useapp.use语法、解析规则完全一样,区别只是作用范围:

router.use([path,] ...middleware)

第一个path同样是可选;

不传时默认/,但这里的/是相对于 Router 被挂载的位置。


六、四种常见用法

用法 1:Router 级全局中间件

const router = Router(); router.use((req, res, next) => { console.log("进入 todo 模块", req.path); next(); }); router.get("/", ...); router.get("/:id", ...);

配合:

app.use("/api/todos", router);

效果:

只有访问/api/todos/*时才会进这个中间件;

/health不会。


用法 2:Router 内带子路径

router.use("/archive", archiveRouter);

若:

app.use("/api/todos", router);

则完整路径是:

/api/todos/archive/*

用法 3:某个子路径 + 中间件

router.use("/:id", validateId, loadTodo);

只对:

/api/todos/123

这类带:id的请求执行validateIdloadTodo

/api/todos

(列表)不会走。


用法 4:错误处理

router.use((err, req, res, next) => { res.status(500).json({ error: err.message }); });

app.use一样,4 个参数表示错误中间件,但只处理这个 router 链路上抛出的错误。


总结

app.use 本质

app.use([path,] ...middleware);
  • path 可选

  • middleware 可多个

  • Router 本质也是中间件


Router 本质

const router = Router();

Router 是一个中间件容器:

router.get(...) router.post(...) router.use(...)

最后通过:

app.use("/prefix", router);

挂载到主应用。


路径拼接规则

app.use("/api/todos", router); router.get("/");

最终:

GET /api/todos

app.use("/api/todos", router); router.get("/:id");

最终:

GET /api/todos/:id

错误中间件识别规则

(err, req, res, next)

只要参数个数为 4,Express 就会把它当成错误处理中间件。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询