当前位置: 首页 > news >正文

Node.js 路由与中间件

一、路由(Routing)

1. 什么是路由?

路由是指根据客户端的请求路径和请求方法,将请求分配给对应的处理函数的机制。简单来说,就是"当用户访问某个 URL 时,服务器应该执行什么操作"。

2. 基本路由实现

在 Node.js 中,可通过原生 http 模块手动实现路由,也可使用 Express 框架简化操作。

(1)原生 http 模块实现
const http = require('http');const server = http.createServer((req, res) => {const { method, url } = req;// 设置响应头res.setHeader('Content-Type', 'text/plain; charset=utf-8');// 路由判断if (method === 'GET' && url === '/') {res.end('首页');} else if (method === 'GET' && url === '/about') {res.end('关于我们');} else if (method === 'POST' && url === '/login') {res.end('登录接口');} else {res.statusCode = 404;res.end('404 页面未找到');}
});server.listen(3000, () => {console.log('服务器运行在 http://localhost:3000');
});
(2)Express 框架实现

Express 内置了路由处理机制,更简洁高效:

const express = require('express');
const app = express();// GET 请求 - 首页
app.get('/', (req, res) => {res.send('首页');
});// GET 请求 - 关于页
app.get('/about', (req, res) => {res.send('关于我们');
});// POST 请求 - 登录接口
app.post('/login', (req, res) => {res.send('登录成功');
});// 404 处理
app.use((req, res) => {res.status(404).send('404 页面未找到');
});app.listen(3000, () => {console.log('Express 服务器运行在 http://localhost:3000');
});

3. 路由参数

用于匹配动态路径(动态参数)(如 /user/123 中的 123 为用户 ID):

// Express 中获取路由参数
app.get('/user/:id', (req, res) => {// req.params 包含路由参数const userId = req.params.id;res.send(`用户 ID:${userId}`);
});// 多参数示例
app.get('/user/:id/post/:postId', (req, res) => {res.send(`用户 ID:${req.params.id},文章 ID:${req.params.postId}`);
});

4. 路由模块化

当路由较多时,可拆分到单独文件中:

(1)创建路由模块(routes/user.js
const express = require('express');
const router = express.Router(); // 创建路由实例// 用户列表
router.get('/', (req, res) => {res.send('用户列表');
});// 用户详情
router.get('/:id', (req, res) => {res.send(`用户 ${req.params.id} 的详情`);
});module.exports = router; // 导出路由
(2)在主文件中使用
const express = require('express');
const app = express();
const userRouter = require('./routes/user');// 挂载路由,所有以 /user 开头的请求都会交给 userRouter 处理
app.use('/user', userRouter);app.listen(3000);

二、中间件(Middleware)

1. 什么是中间件?

中间件是在请求到达路由处理函数之前执行的函数,可用于处理请求、修改响应、实现功能复用(如日志记录、身份验证等)。

中间件的基本格式:

app.use((req, res, next) => {// 处理逻辑next(); // 调用 next() 进入下一个中间件或路由
});
  • req:请求对象
  • res:响应对象
  • next:函数,调用后将控制权交给下一个中间件

2. 中间件的分类

(1)应用中间件

绑定到 app 实例的中间件,对所有请求生效:

// 日志中间件
app.use((req, res, next) => {console.log(`${new Date().toLocaleString()} - ${req.method} - ${req.url}`);next(); // 必须调用 next(),否则请求会被挂起
});// 验证中间件(仅对 /admin 路径生效)
app.use('/admin', (req, res, next) => {const isLogin = true; // 模拟登录状态if (isLogin) {next(); // 已登录,继续} else {res.send('请先登录');}
});
(2)路由中间件

与路由绑定的中间件,仅对特定路由生效:

// 路由级中间件(检查用户权限)
const checkPermission = (req, res, next) => {const hasPermission = true; // 模拟权限检查if (hasPermission) {next();} else {res.status(403).send('没有权限');}
};// 应用到路由
app.get('/admin/user', checkPermission, (req, res) => {res.send('用户管理页面');
});
(3)错误处理中间件

专门处理错误的中间件,有 4 个参数(err, req, res, next):

app.use((err, req, res, next) => {console.error('错误:', err.stack);res.status(500).send('服务器内部错误');
});// 使用示例
app.get('/error', (req, res, next) => {try {throw new Error('自定义错误');} catch (err) {next(err); // 传递错误到错误中间件}
});
(4)第三方中间件

需通过 npm 安装的中间件(如 cors 处理跨域、morgan 日志记录):

npm install cors morgan
const cors = require('cors');
const morgan = require('morgan');// 允许跨域
app.use(cors());// 打印请求日志
app.use(morgan('combined'));

三. 总结

1. 路由:控制请求的分发,根据 method 和 url 匹配对应的处理函数,支持动态参数和模块化拆分。​
2. 中间件:在请求处理流程中插入自定义逻辑,可实现日志、验证、错误处理等功能,按定义顺序执行,通过 next() 传递控制权。

http://www.lryc.cn/news/608561.html

相关文章:

  • DyWA:用于可推广的非抓握操作的动态自适应世界动作模型
  • 浅拷贝与深拷贝的区别
  • 技术面试知识点详解 - 从电路到编程的全栈面经
  • 机试备考笔记 2/31
  • linux编译基础知识-头文件标准路径
  • 系统思考:超越线性分析
  • SpringBoot相关注解
  • MybatisPlus-逻辑删除
  • c++之基础B(进制转换)(第三课)
  • ARP协议是什么?ARP欺骗是如何实现的?我们该如何预防ARP欺骗?
  • 存储过程的介绍、基本语法、delimiter的使用
  • HarmonyOS 开发:基于 ArkUI 实现复杂表单验证的最佳实践
  • Makefile 从入门到精通:自动化构建的艺术
  • 【设计模式】 3.设计模式基本原则
  • Kotlin单例模式懒汉模式:LazyThreadSafetyMode.SYNCHRONIZED(2)
  • 未来交通:元宇宙技术重塑出行体验
  • 第15届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2024年1月28日真题
  • 深入 Go 底层原理(二):Channel 的实现剖析
  • 网易云音乐硬刚腾讯系!起诉SM娱乐滥用市场支配地位
  • Seal Report:一款免费开源的报表工具
  • 联合索引全解析:一棵树,撑起查询的半边天
  • TCL --- 列表_part2
  • 逻辑回归 银行贷款资格判断案列优化 交叉验证,调整阈值,下采样与过采样方法
  • Conda和pip的使用记录
  • Python 字典为什么查询高效
  • Python 全局解释器锁
  • 如何在`<link type=“icon“ href=`的`href`中写SVG并使用path标签? 笔记250802
  • C++:std::array vs 原生数组 vs std::vector
  • 通俗易懂解释Java8 HashMap
  • 计数组合学7.11(RSK算法)