WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门

news2024/12/27 7:50:07

作为一个使用Node.js多年的开发者,我已经习惯于用Node.js写一些web应用来为工作服务,因为实现快速、部署简单、自定义强。今天我们一起来学习一个全栈工程师必备技能:web路由。(观看此文的前提是默认你已经装好nonde.js了)

Node.js 中的路由是构建 Web 应用的核心概念之一,帮助我们根据用户请求的 URL 和 HTTP 方法(GET、POST 等)做出不同的响应。

下面我们由浅入深,循序渐进地讲解 Node.js 的路由实现:


1. 什么是路由?

【路由(Routing)】是指确定服务器响应用户请求的方式,也就是你访问网站的哪个路径,服务器根据路径响应你相应的内容。

比如某网站 www.duniang.com/路由1 、 www.duniang.com/路由1/路由1的儿子

路由主要根据两个要素:

  • 请求的 URL(如 /home/about
  • 请求的方法(如 GETPOSTPUTDELETE
    关于这一点网上有很多讨论,很多人基本就是 GET /  POST 一招吃遍天下,这也无可厚非。不过建议开发者还是老老实实 规规矩矩的把习惯养好,该PUT就PUT 该DELETE就DELETE。

2. 用原生 Node.js 实现简单路由

用原生的 http 模块,我们可以通过检查请求的 URL 和方法来实现路由。以下是一个简单的例子:

const http = require('http');

const server = http.createServer((req, res) => {
  const { url, method } = req;

  if (url === '/' && method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Welcome to Home Page');
  } else if (url === '/about' && method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('This is the About Page');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('Page Not Found');
  }
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

特点:

  • 手动判断 urlmethod
  • 适合学习,但不适合复杂应用,代码难以维护。

http是node内核自带的网络服务模块,可以快速创建http服务。 

将上面代码命名为 app.js ,使用  node app.js 命令 启动

创建了一个端口为3000的 webServer,我我们可以通过 http://127.0.0.1:3000访问:


3. 使用 Express 简化路由

http 这个模块使用起来还是不太方便,观感不太好,代码量也比较大,如果路由复杂,要写很多代码。所以就有了 Express

Express 是一个轻量级、流行的 Node.js 框架,它对路由的处理非常直观。我们可以用它创建清晰、可扩展的路由。

安装 Express:

npm install express

简单路由示例:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Welcome to Home Page');
});

app.get('/about', (req, res) => {
  res.send('This is the About Page');
});

// 404 handler
app.use((req, res) => {
  res.status(404).send('Page Not Found');
});

app.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

优点:

  • 简洁的 API,如 app.get()app.post()
  • 支持中间件,可以扩展功能(如验证、日志)。

上面这个代码就清楚多了。 Express在现实中的应用非常广泛,它简单、直观,使用起来也很灵活。


4. 动态路由

动态路由允许我们为具有相似结构的 URL 创建单一路由。例如,处理用户的 ID:

app.get('/user/:id', (req, res) => {
  const userId = req.params.id; // 获取动态参数
  res.send(`User ID is ${userId}`);
});

访问 http://localhost:3000/user/123,响应为:

User ID is 123

请注意,这里的网址是 /user/minstbe  后面这个/minstbe 本来应该是一个路由,但是这里被定义为一个参数 ,它等效于 /user?id=minstbe 。很多时候我们如果不希望网页带有问号、等于号,就可以用这种方式来定义传参。

req.params:存储动态 URL 参数。

 如果我们在服务器端 console.log(req.params)  就会看到打印出了这个Object类型的参数:


5. 路由模块化

当路由逻辑增多时,我们可以将路由分离到单独的文件中,提高代码的可读性和可维护性。实际生产过程中,还会用到更加高级的分离方式 这个我们以后再介绍。

1. 创建路由模块(routes/user.js):

在webServer的主目录下创建 文件夹 routes ,并创建user.js,用来对 /user做出响应 

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

router.get('/:id', (req, res) => {
  const userId = req.params.id;
  res.send(`User Profile of ID: ${userId}`);
});

module.exports = router;

2. 在主文件中引入路由模块(index.js):

const express = require('express');
const app = express();
const userRoutes = require('./routes/user'); // 这里引入了这个路由模块

app.use('/user', userRoutes); // 访问路径为 /user/:id

app.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

上面两个文件结合使用,启动index.js 后如下: 


6. 中间件与路由结合

中间件是在路由处理前或后执行的一段代码,用于实现日志、验证、解析等功能。

中间件在Node.js的webServer中非常重要,很多功能都是在中间件实现的,通过中间件处理获取到的内容,再交给后面的api来处理。 

示例:

const logger = (req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next(); // 必须调用 next() 才能进入下一个中间件或路由
};

app.use(logger);

app.get('/', (req, res) => {
  res.send('Home Page with Logger');
});

 下面是在/user 之前 加入了一个中间件,也就是显示 访问方式 和 路径,然后再继续 交给 /user判断处理:(请注意控制台的输出)


7. 高级路由功能

  1. 处理多种 HTTP 方法:
app.route('/book')
  .get((req, res) => res.send('Get a book'))
  .post((req, res) => res.send('Add a book'))
  .put((req, res) => res.send('Update a book'));

app.route() 是 Express 提供的一个链式路由定义方法,用于处理针对 同一路径 的多个 HTTP 方法(如 GETPOSTPUT 等)的请求。

工作原理

app.route(path) 会创建一个单独的路由路径对象,可以通过链式调用分别为该路径定义不同的 HTTP 方法处理逻辑。这种写法能使代码更加清晰、结构更紧凑。


具体解析

app.route('/book')
  .get((req, res) => res.send('Get a book'))
  .post((req, res) => res.send('Add a book'))
  .put((req, res) => res.send('Update a book'));
  1. app.route('/book')
    定义了一个路径 /book 的路由。

  2. .get()

    • 处理 GET /book 请求。
    • 回调函数 (req, res) 用于返回一个响应,当前返回内容是 'Get a book'
  3. .post()

    • 处理 POST /book 请求。
    • 回调函数 (req, res) 返回 'Add a book'
  4. .put()

    • 处理 PUT /book 请求。
    • 回调函数 (req, res) 返回 'Update a book'

等价写法

上述代码的功能可以用多个单独的路由来实现:

app.get('/book', (req, res) => res.send('Get a book'));
app.post('/book', (req, res) => res.send('Add a book'));
app.put('/book', (req, res) => res.send('Update a book'));

对比:

  • 使用 app.route() 方法:
    • 逻辑集中在一个地方,便于管理和阅读。
    • 适合路径相同但处理方法不同的场景。
  • 使用分开定义的路由:
    • 路径重复,代码冗长,不够直观。

扩展:何时使用 app.route()

  1. 当一个路径需要支持多种 HTTP 方法时,比如 /book 需要处理 GETPOSTPUT
  2. 希望减少路径的重复书写,提高代码可读性和组织性。

注意:

  • app.route() 仅适用于同一个路径。如果处理的路径不同(比如 /book/author),仍需单独定义路由。
  • 它仅是 Express 提供的一种语法糖,本质上和单独写多个路由的逻辑一样。
  1. 正则匹配路由:
app.get(/.*fly$/, (req, res) => {
  res.send('Route matched with /.*fly$/');
});
// 例如,访问 /butterfly、/dragonfly 都可以匹配

好了 今天,就简单介绍一下,下次再继续!

  1. 原生实现:适合理解底层原理。
  2. Express:简化路由逻辑,是构建 Web 应用的主流选择。
  3. 动态路由:为类似的请求模式处理提供便利。
  4. 模块化路由:适合复杂项目。
  5. 中间件支持:增强功能的可扩展性。

可以从简单的例子开始尝试,然后逐渐增加复杂度,适应实际的开发场景!你想尝试哪种实现?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2254254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大模型分类3—按功能特性

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl根据功能特性,大模型可分为生成式、分析式和交互式大模型。 1. 大模型分类概述 1.1 生成式大模型 生成式大模型的核心能力在于其创造性,能够独立生成新的数据样本,如文本、图像和音频等。这类…

VUE拖拽对象到另一个区域

最近有个需求是需要在web端定制手机的界面UI(具体实现比较复杂,此处不做阐述,此文章只说明拖拽效果实现),为了方便用户操作,就想实现这种效果:从右侧的图标列表中拖拽图标到左侧模拟的手机界面上…

iOS平台接入Facebook登录

1、FB开发者后台注册账户 2、完善App信息 3、git clone库文件代码接入 4、印尼手机卡开热点调试 备注: 可能遇到的问题: 1、Cocos2dx新建的项目要更改xcode的git设置,不然卡在clone,无法在线获取FBSDK 2、动态库链接 需要在…

传输层TCP_三次握手四次挥手的过程

三次握手四次挥手 三次握手 三次握手

小迪笔记 第四十五天 sql 注入进阶 :二次注入,堆叠注入,数据读取(load_file)加外带

二次注入 概念:就是我们注入的语句(刚注入时 不会产生影响)但是我们的恶意代码会进入数据库 他在被二次利用的时候就会进行执行 这个就是二次注入 这个的典型案例就是账号密码的修改 : 大家应该也知道 账号注册一般是禁止你使…

【SNIP】《An Analysis of Scale Invariance in Object Detection – SNIP》

CVPR-2018 Singh B, Davis L S. An analysis of scale invariance in object detection snip[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2018: 3578-3587. https://github.com/bharatsingh430/snip?tabreadme-ov-file 文章目录 …

【C++|Linux|计网】构建Boost站内搜索引擎的技术实践与探索

目录 1、项目的相关背景 2.搜索引擎的相关宏观原理 3.搜索引擎技术栈和项目环境 4.正排索引vs倒排索引-搜索引擎具体原理 5.编写数据去标签与数据清洗的模块 Parser 5.1.去标签 目标: 5.2.代码的整体框架: EnumFile函数的实现: Enu…

ComfyUI绘画|提示词反推工作流,实现自动化书写提示词

今天先分享到这里~ ComfyUI绘画|关于 ComfyUI 的学习建议

高频面试题(含笔试高频算法整理)基本总结回顾20

干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…

【AI模型对比】AI新宠Kimi与ChatGPT的全面对比:技术、性能、应用全揭秘

文章目录 Moss前沿AI技术背景Kimi人工智能的技术积淀ChatGPT的技术优势 详细对比列表模型研发Kimi大模型的研发历程ChatGPT的发展演进 参数规模与架构Kimi大模型的参数规模解析ChatGPT的参数体系 模型表现与局限性Kimi大模型的表现ChatGPT的表现 结论:如何选择适合自…

性能测试基础知识jmeter使用

博客主页:花果山~程序猿-CSDN博客 文章分栏:测试_花果山~程序猿的博客-CSDN博客 关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长! 目录 性能指标 1. 并发数 (Con…

如何通过 Windows 自带的启动管理功能优化电脑启动程序

在日常使用电脑的过程中,您可能注意到开机后某些程序会自动运行。这些程序被称为“自启动”或“启动项”,它们可以在系统启动时自动加载并开始运行,有时甚至在后台默默工作。虽然一些启动项可能是必要的(如杀毒软件)&a…

基于PSO粒子群优化的CNN-LSTM-SAM网络时间序列回归预测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频&#xff09…

STM32 Jlink Flash读写固件数据

目录 一、从单片机读数据 1.创建工程XX.jflash,已经有的工程不需要创建直接打开 2.创建完成,连接jlink 3.读取整个芯片的数据 4.读取完成后保存数据 5.选择保存的数据格式,以及位置,读数据完成 二、写固件数据到单片机 1.创建工程XX.j…

Scrapy解析JSON响应v

在 Scrapy 中解析 JSON 响应非常常见,特别是当目标网站的 API 返回 JSON 数据时。Scrapy 提供了一些工具和方法来轻松处理 JSON 响应。 1、问题背景 Scrapy中如何解析JSON响应? 有一只爬虫(点击查看源代码),它可以完美地完成常规的HTML页面…

波动理论、传输线和S参数网络

波动理论、传输线和S参数网络 传输线 求解传输线方程 对于传输线模型,我们通常用 R L G C RLGC RLGC 来表示: 其中 R R R 可以表示导体损耗,由于电子流经非理想导体而产生的能量损耗。 G G G 表示介质损耗,由于非理想电介质…

鸿蒙开发——使用ArkTs处理XML文本

1、概 述 XML(可扩展标记语言)是一种用于描述数据的标记语言,旨在提供一种通用的方式来传输和存储数据,特别是Web应用程序中经常使用的数据。XML并不预定义标记。因此,XML更加灵活,并且可以适用于广泛的应…

微信小程序介绍-以及写项目流程(重要)

前言:本篇文章介绍微信小程序以及项目介绍: 文章介绍:介绍了微信小程序常用的指令、组件、api。tips:最好按照官方文档来进行学习,大致可以我的目录来学习,对于写项目是没有问题的 微信小程序官方文档https…

嵌入式蓝桥杯学习5 定时中断实现按键

Cubemx配置 打开cubemx。 前面的配置与前文一样,这里主要配置基本定时器的定时功能。 1.在Timer中点击TIM6,勾选activated。配置Parameter Settings中的预分频器(PSC)和计数器(auto-reload Register) 补…

特别分享!SIM卡接口功能及其电路设计相关注意事项

SIM卡接口功能及其电路设计相关注意事项对电子工程师来说非常重要。SIM卡接口用于连接SIM卡并读取SIM卡信息,以便在注册4G网络时进行鉴权身份验证,是4G通信系统的必要功能。 一、SIM卡接口功能描述 Air700ECQ/Air700EAQ/Air700EMQ系列模组支持1路USIM接…