【node进阶】深度解析Express框架--路由、中间件

news2024/11/17 9:29:42

✅ 作者简介:一名普通本科大三的学生,致力于提高前端开发能力
✨ 个人主页:前端小白在前进的主页
🔥 系列专栏 : node.js学习专栏
⭐️ 个人社区 : 个人交流社区
🍀 学习格言: ☀️ 打不倒你的会使你更强!☀️


🔥前言

国庆期间,也不能停止学习!上一篇文章讲解了express的入门,本节开始我们将进入到核心阶段的学习,核心阶段包含了路由、中间件、编写接口三大块内容,本篇文章将从路由和中间件讲起,详细讲解路由、中间件的定义和应用。快快看过来吧😛😛

在这里插入图片描述


📃目录

  • 初识路由
    • 路由的概念
    • Express中的路由
    • Express中路由实例
    • 路由的匹配过程
  • 路由实操
    • 简单使用
    • 模块化路由
  • 初识中间件
    • 中间件定义(与生活结合)
    • 中间件调用过程
    • Express中间件格式
    • next()的作用
  • Express中间件实际体验
    • 中间件的作用
    • 局部生效的中间件
    • 中间件的使用注意事项
  • 中间件的分类
  • 自定义中间件
  • 中间件实际使用场景示例
  • 小结

初识路由

路由的概念

广义上来讲,路由就是映射关系。nodejs中的路由其实就是url地址响应函数之间的映射关系一个url地址响应一个html页面。就是将一个路径匹配关系的业务提取到一个单独的js文件当中。

说了这么多,肯定有小伙伴们还是不理解,咱们就拿生活中的例子开刀:在我们与10086通话的时候,它的人工机器人总会提醒我们如果你想办理xxx业务,请输入按键x,这样的关系不就是映射关系吗?
在这里,路由是按键服务之间的映射关系

Express中的路由

Express 中,路由指的是客户端的请求服务器处理函数之间的映射关系
Express 中的路由分三部分组成,分别是请求的类型请求的 URL 地址处理函数,格式如下:

app.METHOD(PATH,HANDLER)

Express中路由实例

//匹配get请求,并且请求的url地址为`/`
app.get('/',(req,res)=>{
    res.send('hello world')
})
//匹配post请求,并且请求的url地址为`/login`
app.post('/login',(req,res)=>{
    res.send('Post Request')
})

路由的匹配过程

在上面说了匹配这个词。这个词到底是啥意思呢?每当一个请求到达服务器之后,需要先经过路由的匹配,只有匹配成功之后,才会调用对应的处理函数
在匹配时,会按照路由的顺序进行匹配,如果请求类型请求的 URL 同时匹配成功,则 Express 会将这次请求,转交给对应的 function 函数进行处理。
在这里插入图片描述

匹配注意事项:

  1. 按照定义的先后顺序进行匹配
  2. 请求类型请求的url同时匹配成功,才会调用对应的处理函数

路由实操

简单使用

//引入express模块
const express = require('express')
//创建web服务器,取名为app,实质就是实例化
const app = express()

//挂载路由
app.get('/',(req,res)=>{
    res.send('hello world')
})
app.post('/',(req,res)=>{
    res.send('Post Request')
})
//监听服务器,启动web服务器
app.listen(80,()=>{
    console.log('http://127.0.0.1');
})

模块化路由

为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块。将路由抽离为单独模块的步骤如下:

  1. 创建路由模块对应的 .js 文件
  2. 调用 express.Router() 函数创建路由对象
  3. 向路由对象上挂载具体的路由
  4. 使用 module.exports 向外共享路由对象
  5. 使用 app.use() 函数注册路由模块

具体示例:

  • 创建单独的路由模块

    const express = require('express')
    //创建路由对象
    const router = express.Router()
    //获取用户列表的路由
    router.get('/user/list',function(req,res){
       res.send('Get user list')
    })
    //添加用户的路由
    router.post('/user/add',function(req,res){
       res.send('Add new user')
    })
    //向外导出路由对象
    module.exports = router
    
  • 注册路由模块

    const express = require('express')
    const app = express()
    
    //1.导入路由模块
    const router = require('./router')
    //注册路由模块,并添加统一的访问前缀 /api
    app.use('/api',router)
    
    //app.use()作用是全局注册中间件
    app.listen(80,()=>{
        console.log('http://127.0.0.1');
    })
    

初识中间件

中间件定义(与生活结合)

中间件(Middleware)是一种功能的封装方式,主要是指封装所有http请求细节处理的方法;http的请求通常包含了许多的内容,因此可以利用中间件来简化及隔离这些基础设施业务逻辑之间的细节。也可以去总结一句话,中间件就是:特指业务流程的中间处理环节

黑马哥举了一个生活的例子帮助我们更好的知道什么是中间件:污水处理的中间环节,在处理污水的时候,一般都要经过三个处理环节,从而保证处理过后的废水,达到排放标准。
在这里插入图片描述
处理污水的这三个中间处理环节,就可以叫做中间件


中间件调用过程

当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理
在这里插入图片描述


Express中间件格式

Express 的中间件,本质上就是一个 function 处理函数,Express 中间件的格式如下:
在这里插入图片描述

注意:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res


next()的作用

next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由
在这里插入图片描述


Express中间件实际体验

首先需要知道什么是全局生效的中间件:客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。
整体代码如下:

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


// const mw = function(req,res,next) {
//     console.log('这是最简单的中间件函数');
//     //把流转关系,转交给下一个中间件或路由
//     next()
// }
// //将mw注册为全局生效的中间件
// app.use(mw)

//这是定义全局中间件的简化方式
app.use((req,res,next)=> {
    const time = Date.now()
    console.log('调用了第一个全局中间件');
    req.startTime = time
    next()
})
//定义第二个全局中间件
app.use((req,res,next)=>{
    console.log('调用了第二个全局中间件');
    next()
})
app.get('/',(req,res)=>{
    console.log('调用了 / 这个路由');
    res.send('home page' + req.startTime)
})

app.post('/user',(req,res)=>{
    console.log('调用了 /user 这个路由');
    res.send('User page' + req.startTime)
})
app.listen(80,()=>{
    console.log('http://127.0.0.1');
})

中间件的作用

多个中间件之间,共享同一份 req 和 res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
在这里插入图片描述


局部生效的中间件

不使用 app.use() 定义的中间件,叫做局部生效的中间件。
示例代码如下:

const express = require('express')
const app = express()
//定义中间件函数
const mw1 = (req,res,next)=>{
    console.log('这是中间件函数1');
    next()
}
//定义中间件函数
const mw2 = (req,res,next)=>{
    console.log('这是中间件函数2');
    next()
}
//定义路由
//使用局部中间件第一种方法
app.get('/',mw1,mw2,(req,res)=>{
    res.send('home page')
})
//使用局部中间件第二种方法
app.get('/user',[mw1,mw2],(req,res)=>{
    res.send('hello user')
})
app.listen(80,()=>{
    console.log('http://127.0.0.1');
})

中间件的使用注意事项

  1. 一定要在路由之前注册中间件
  2. 客户端发送过来的请求,可以连续调用多个中间件进行处理
  3. 执行完中间件的业务代码之后,不要忘记调用 next() 函数
  4. 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
  5. 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象

中间件的分类

为了方便大家理解和记忆中间件的使用,Express 官方把常见的中间件用法,分成了 5 大类,分别是:

  • 应用级别的中间件
    通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件.这一种中间件就是上面我们代码写法。

  • 路由级别的中间件
    绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app 实例上,路由级别中间件绑定到 router 实例上.

  • 错误级别的中间件
    错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题
    格式:错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)

    代码示例:

    const express = require('express')
    const app = express()
    //定义路由
    app.get('/',(req,res)=>{
        throw new Error('服务器内部发生了错误!')
        res.send('home page')
    })
    //定义错误级别的中间件,捕获整个项目的异常情况,从而防止程序的崩溃  
    app.use((err,req,res,next)=>{
        console.log('发生了错误!' + err.message);
        res.send('Error:' + err.message)
    })
    app.listen(80,()=>{
        console.log('http://127.0.0.1');
    })
    

    注意:错误级别的中间件,必须注册在所有路由之后

  • Express 内置的中间件
    自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 Express 项目的开发效率和体验:
    express.static 快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)
    express.json 解析 JSON 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)
    express.urlencoded 解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)

    //配置解析application/json 格式数据的内置中间件
    app.use(express.json())
    //配置解析 application/x-www-form-urlencoded 格式数据的内置中间件
    app.use(express.urlencoded({extended:false}))
    
  • 第三方的中间件
    非 Express 官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。
    例如:在 express@4.16.0 之前的版本中,经常使用 body-parser 这个第三方中间件,来解析请求体数据。使用步骤如下:

    • 运行 npm install body-parser 安装中间件
    • 使用 require 导入中间件
    • 调用 app.use() 注册并使用中间件

    注意:Express 内置的 express.urlencoded 中间件,就是基于 body-parser 这个第三方中间件进一步封装出来的。


自定义中间件

自己手动模拟一个类似于 express.urlencoded 这样的中间件,来解析 POST 提交到服务器的表单数据

  1. 封装一个中间件处理函数(这个js文件名为:custom-body-paser.js)

    const qs = require('querystring')
    const bodyPaser = (req,res,next)=>{
        let str = ''  //专门用来存储客户端发过来的数据
        // node.js用req.on(data)接收客户端的数据;
        req.on('data',(chunk)=>{
            str += chunk
        })
        req.on('end',()=>{
            console.log(str);
            const body = qs.parse(str)
            req.body = body
            next()
        })
    }
    
    module.exports = bodyPaser
    
  2. 模块调用

    const express = require('express')
    
    const app = express()
    const customBodyPaser = require('./custom-body-paser')
    //解析表单数据的中间件
    app.use(customBodyPaser)
    
    app.post('/user',(req,res)=>{
        res.send(req.body)
    })
    
    app.listen(80,()=>{
        console.log('http://127.0.0.1');
    })
    

中间件实际使用场景示例

讲解了中间件的知识,大家可能还是看的一脸懵逼,不知道中间件在开发中的具体作用能干啥,如果你学过了vue,其实你很容易就明白中间件其实就是拦截器,跟路由守卫作用一样,在实际开发中有个重要的环节,如果用户没有登录的话,那么该用户就不能访问一些页面,并且也不会获取到一些信息,比如:如果我知道个人中心的url地址,但是我没有登录,我却可以去进入我的个人中心页面,这不是扯淡吗?,中间件就可以很好的解决这个问题。
具体小demo如下:

const loginCheck = (req, res, next) => {
    if (某个登录成功的条件) {
       next(); // 登录成功执行next
    } else {
       res.json({
         err: -1,
         msg: '登录失败'
	})
	res.redirect('/adminlogin');  // 将用户重定向到登录页面
    }
}
// 若在登录状态下,loginCheck会执行next函数,从而执行第二个中间件,获取博客列表。
app.get('/api/blog/list', loginCheck, (req, res, next) => {
    获得博客列表
})

小结

Express框架中路由和中间件都是必须用的,好多人在中间件的理解上总是差点意思,不能够灵活的运用中间件,你的项目将会出现大大小小的问题,因此,中间件的学习必须是要吃透的,如果你想自己结合vue+node写一个整合性项目,中间件的使用是必不可少的!继续加油吧,少年!😀😀


👑书写不易,希望大家能够给予三连支持,期待我更好的文章哟👑

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

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

相关文章

完全卸载vscode

背景 由于插件崩溃、不正确操作等导致vscode出现异常现象,如:代码高亮失效、无法进行转到定义等,此时的vscode就需要重新完全卸载删除再安装,恢复初始化。 步骤 1、卸载vscode: 任何方法都可以,比如win…

vue 遍历数组

1.forEach(): 遍历数组 需要一个回调函数作为参数 回调函数的形参: ①. value: 遍历数组的内容 ②.index: 对应数组的索引 ③.array: 数组本身 forEach() 方法主要是用于调用数组的每个元素,并将元素传递给回调函数。 注:对于空数组不会执行回调函数 语法: ar…

jsoup 框架的使用指南

概述 参考: 官方文档jsoup的使用JSoup教程jsoup 在 GitHub 的开源代码 概念简介 jsoup 是一款基于 Java 的 HTML 解析器,它提供了一套非常省力的 API,不但能直接解析某个 URL 地址、HTML 文本内容,而且还能通过类似于 DOM、CS…

刷题日常计~JS①

作者 : SYFStrive 博客首页 : 点击跳转HomePage 📜: 初编程JavaScript之每天10题 👉 从质变到量变💪 📌:个人社区(欢迎大佬们加入) 👉:社区链接&#x1f5…

Vue常见报错及解决方案

写代码的过程中一定会遇到报错,遇到报错不要担心,认真分析就可以解决报错,同时积累经验,早日成为大牛👍 本文会整理一些在编码过程中遇到的常见报错,共同学习。 一、报错结构 二、常见问题总结及解决方法 …

微信小程序跳转外部链接

微信小程序跳转外部链接 在开发小程序过程中,我们可能会有这样的需求,在小程序中打开H5或者外部链接 实现方法如下: 1、配置业务域名 小程序管理后台——开发(开发管理)——开发设置:新增业务域名 在这里将你需要的外部链接域…

超详细的正则表达式的使用方法,学不会找我

正则表达式的基本使用 前言: 在我们开发过程中,有很多地方需要用到正则表达式。如验证用户登录信息、手机号、邮箱地址等等。那你都会正则表达式的哪几个方法呢? 首先,我们要知道什么是正则表达式。 正则表达式的定义&#xff…

节流还在用JS吗?CSS也可以实现哦

函数节流是一个我们在项目开发中常用的优化手段,可以有效避免函数过于频繁的执行。一般函数节流用在scroll页面滚动,鼠标移动等。 为什么需要节流呢,因为触发一次事件就会执行一次事件,这样就形成了大量操作dom,会出现卡顿的情况…

ES6模块化(默认导入导出、按需导入导出、直接导入)

一、介绍ES6模块化 ES6 模块化规范是浏览器端与服务器端通用的模块化规范,ES6模块化的出现前端开发者不再需要额外的学习其他的模块化规范。 二、ES6 模块化规范中定义: 1.每个 js 文件都是一个独立的模块 2.导入其它模块成员使用 import 关键字 3.向外…

React组件——类组件

一、组件的概念 使用组件的方式进行编程,可以提高开发效率,提高组件的复用性、提高代码的可维护性和可扩展性 React定义组件的方式有两种 类组件:React16.8版本之前几乎React使用的都是类组件 函数组件:React16.8之后,函数式组件使用的越…

2023高频前端面试题(含答案)

一、简单页面 1、CSS选择器样式优先级 2、CSS实现三列布局(左右固定宽度,中间自适应) (1)CSS浮动 第一个float:left,第二个float:right,第三个设置margin-left和margin-right (2&am…

什么是Mixin?带你了解Vue中的Mixin混入

什么是Mixin?本篇文章带大家了解一下Vue中的Mixin混入,介绍Mixin和Vuex的区别,Mixin的使用方法,希望对大家有所帮助! Vue框架现在基本上已经占据了前端的半壁江山,Vue的数据驱动和组件化的思想深入人心。Vu…

web前端-JavaScript中的数组详解

🐚作者简介:苏凉(专注于网络爬虫,数据分析,正在学习前端的路上) 🐳博客主页:苏凉.py的博客 🌐系列总专栏:web前端基础教程 👑名言警句&#xff1a…

我用尽了洪荒之力,解开了ChatGPT 写前端代码的封印,结果...

我用尽了洪荒之力,解开了ChatGPT 写前端代码的封印介绍ChapGPT 听起来好得令人难以置信,所以让我们让它为我们编写一些 JS 代码。我想看看它是否可以解决我作为前端开发人员每天所做的任务。是驴子是马拉出来溜溜,我们还是直接进入主题一探究…

Vite + Vue3 +Vant4构建项目时,按需引入使用Toast组件,引用 showToast 时出现编译报错的解决方案

Vite Vue3 Vant4构建项目时,按需引入使用Toast组件,引用 showToast 时出现编译报错的解决方案 文章目录Vite Vue3 Vant4构建项目时,按需引入使用Toast组件,引用 showToast 时出现编译报错的解决方案一.问题定位二.以下为完整解决…

React+Mobx|基本使用、模块化

欢迎来到我的博客 📔博主是一名大学在读本科生,主要学习方向是前端。 🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏 🛠目前正在学习的是🔥 R e a c t 框架 React框架 Reac

【小程序项目开发 -- 京东商城】uni-app 商品分类页面(上)

🤵‍♂️ 个人主页: 计算机魔术师 👨‍💻 作者简介:CSDN内容合伙人,全栈领域优质创作者。 🌐 推荐一款找工作神器网站: 点击跳转牛客网 |笔试题库|面试经验|实习招聘内推| 还没有账户的小伙伴 速速点击链接…

前端 --- HTML

文章目录1. HTML 结构1.1 HTML 文件基本结构1.2 VsCode 中 使用 HTML 的快捷键2. HTML 常见标签2.1 注释标签2.2 标题标签2.3 段落标签2.4 换行标签2.5 格式化标签2.6 图片标签2.7 超链接标签2.8 表格标签2.9 列表标签2.10 表单标签form 标签input 标签① 文本框② 密码框③ 单…

Vue中实现路由跳转的三种方式详细分解

vue中实现路由跳转的三种方式 目录 vue中实现路由跳转的三种方式 一、使用vue-router 1.下载vue-router模块到当前工程 2.在main.js中引入VueRouter函数 3.添加到Vue.use()身上 – 注册全局RouterLink和RouterView组件 4.创建路由规则数组 – 路径和组件名对应关系 5…

CSS flex布局最后一行左对齐的常用方法

一、justify-content 在CSS flex布局中,justify-content属性定义了浏览器之间,如何分配顺着弹性容器主轴 (或者网格行轴) 的元素之间及其周围的空间,可以控制列表的水平对齐方式, justify-content: center; /* 居中排列 */ …