第三方Express 路由和路由中间件

文章目录

  • 1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。
  • 2、Express路由
    • 1.路由方法
    • 2.路由路径
    • 3.路由处理程序
  • 3. 模块化路由
  • 4. Express中间件
    • 1.中间件简介
    • 2.中间件分类
    • 3.自定义中间件


1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。

  1. Request 对象
    request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性
    属性/方法说明
    app当callback为外部文件时,用req.app访问express的实例
    baseUrl获取路由当前安装的URL路径
    body/cookies获得「请求主体」/ Cookies
    fresh/stale判断请求是否还「新鲜」
    hostname/ip获取主机名和IP地址
    originalUrl获取原始请求URL
    params获取路由的parameters
    path获取请求路径
    protocol获取协议类型
    query获取URL的查询参数串
    route获取当前匹配的路由
    subdomains获取子域名
    accepts()检查可接受的请求的文档类型
    acceptsCharsets/acceptsEncodings/acceptsLanguages返回指定字符集的第一个可接受字符编码
    get()获取指定的HTTP请求头
    is()判断请求头Content-Type的MIME类型
  2. Response 对象
    response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据
    属性/方法说明
    app当callback为外部文件时,用req.app访问express的实例
    append()追加指定HTTP头
    set()在res.append()后将重置之前设置的头
    res.cookie(name,value [,option])设置Cookie
    opitiondomain / expires / httpOnly / maxAge / path / secure / signed
    clearCookie()清除Cookie
    download()传送指定路径的文件
    get()返回指定的HTTP头
    json()传送JSON响应
    jsonp()传送JSONP响应
    location()只设置响应的Location HTTP头,不设置状态码或者close response
    redirect()设置响应的Location HTTP头,并且设置状态码302
    render(view,[locals],callback)渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
    send()传送HTTP响应
    sendFile(path [,options] [,fn])传送指定路径的文件 -会自动根据文件extension设定Content-Type
    set()设置HTTP头,传入object可以一次设置多个头
    status()设置HTTP状态码
    type()设置Content-Type的MIME类型

2、Express路由

路由是指应用程序的终端节点 (URI) 如何响应客户端请求。
在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。
Express中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数,格式如下:app.method(path, handler)

1.路由方法

// GET method route
app.get('/', function (req, res) {res.send('GET request')
})// POST method route
app.post('/', function (req, res) {res.send('POST request')
})

app.all() 用于在所有 HTTP 请求方法的路径上加载中间件函数。
无论是使用 GET、POST、PUT、DELETE 还是 http 模块中支持的任何其他 HTTP 请求方法,都会对路由 “/secret” 的请求执行以下处理程序。

app.all('/secret', function (req, res, next) {console.log('all')next() // pass control to the next handler
})

2.路由路径

路由路径可以是字符串、字符串模式或正则表达式。

// acd和abcd
app.get('/ab?cd', function (req, res) {res.send('ab?cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:问号前面字符可有可无

app.get('/ab(cd)?e', function (req, res) {res.send('ab(cd)?e')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:问号前面括号内的字符可有可无

app.get('/ab+cd', function (req, res) {res.send('ab+cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:加号前面字符可无限叠加

app.get('/ab*cd', function (req, res) {res.send('ab*cd')
})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
总结:星号前面的字符为开始,后边的字符为结束字符,中间可以任意字符或数字

app.get(/a/, function (req, res) {res.send('/a/')
})

在这里插入图片描述
在这里插入图片描述
总结:满足正则/a/的都满足此方法

app.get(/.*fly$/, function (req, res) {res.send('/.*fly$/')
})

在这里插入图片描述
在这里插入图片描述

总结:满足正则/.*fly$/以fly字符结束的路由

3.路由处理程序

在没有理由继续当前路由时将控制权传递给后续路由。next(‘route’)
路由处理程序可以采用函数、函数数组或两者的组合形式。

  1. 单个回调函数可以处理路由。

    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res) {res.send('hello abc');
    })
    app.listen(8081, function () {console.log("服务启动")
    })
    
  2. 多个回调函数可以处理一个路由(确保指定对象)next();

    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res, next) {console.log(111)next()
    }, function(req, res) {res.send('hello abc next');
    })
    app.listen(8081, function () {console.log("服务启动")
    })	
    

    在这里插入图片描述
    在这里插入图片描述

  3. 回调函数数组可以处理路由。

    var express = require('express');
    var app = express();
    var a0 = function (req, res, next) {console.log('A0')next()
    }
    var a1 = function (req, res, next) {console.log('A1')next()
    }
    var a2 = function (req, res) {res.send('Hello from A!')
    }
    app.get('/abc', [a0, a1, a2])
    app.listen(8081, function () {console.log("服务启动")
    })
    

    在这里插入图片描述
    在这里插入图片描述

  4. 独立函数和函数数组的组合可以处理路由。

    var express = require('express');
    var app = express();
    var a1 = function (req, res, next) {console.log('A1')next()
    }
    var a2 = function (req, res) {res.send('Hello from A!')
    }
    app.get('/abc', function (req, res, next) {console.log('A0')next()
    },[a1, a2])
    app.listen(8081, function () {console.log("服务启动")
    })
    

    在这里插入图片描述
    在这里插入图片描述

3. 模块化路由

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

将路由抽离为单独模块的步骤如下:
1.创建路由模块对应的.js文件
2.调用express.Router()函数创建路由对象
3.向路由对象上挂载具体的路由
4.使用module.exports向外共享路由对象
5.使用app.use()函数注册路由模块

  1. 创建路由模块
    // router.js   文件
    var express = require('express'); // 1.导入express
    var router = express.Router();    // 2.创建路由对象router.get('/login/info', (req, res) => {   // 3.挂载登录用户信息res.send('Get user list.');
    });
    router.post('/singUp/add', (req, res) => {   // 4.挂载注册用户的路由res.send('Add new user.');
    });
    module.exports = router;  // 5.向外导出路由对象
    
  2. 注册路由模块
    const express = require('express');
    const app = express();
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块
    app.use(userRouter);
    app.listen(8081, () => {console.log('http://127.0.0.1')
    })
    
  3. 为路由模块添加前缀
    // 类似于托管静态资源时,为静态资源统一挂载访问前缀一样
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块,并添加统一的范围前缀 /api 
    app.use('/api', userRouter);
    

4. Express中间件

1.中间件简介

  1. 中间件简介
    中间件是一种特殊的路由处理函数,它可以在请求到达目标处理函数之前,进行一些预处理操作。Express 支持使用中间件来实现各种功能,例如身份验证、请求日志记录,处理 CORS(跨源资源共享)等。
    注意:中间件函数的形参列表中,必须包含next参数,而路由处理函数中只包含req和res。
    next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
    可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用
    const express = require('express');
    const app = express();
    // 一个简单的中间件
    app.use((req, res, next) => {console.log(`Request received at ${new Date()}`);next(); // 将控制权传递给下一个中间件或路由处理器
    });
    // 一个路由处理器,用于处理 GET 请求
    app.get('/', (req, res) => {res.send('Hello, World!');
    });// 启动服务器
    app.listen(8081, () => {console.log('Server is running on port 8081');
    });
    
    在这里插入图片描述
  2. 局部中间件
    不使用app.use()定义的中间件,叫做局部生效的中间件, 中间件只在"当前路由中生效",
    var express = require('express');
    var app = express();var myLogger = function (req, res, next) {console.log('LOGGED')next()
    }
    app.get('/', myLogger, function (req, res) {res.send('Hello World!')
    })
    
    在这里插入图片描述
  3. 中间件的5个使用注意事项
    • 一定要在路由之前注册中间件
    • 客户端发送过来的请求,可以连续调用多个中间件进行处理
    • 执行完中间件的业务代码之后,不要忘记调用next()函数
    • 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
    • 连续调用多个中间件时,多个中间件之间,共享req和res对象
  4. 监听 req 的 data 事件
    在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。
    如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。
    // 定义变量,用来储存客户端发送过来的请求体数据
    let str = ''
    // 监听 req 对象的 data 事件(客户端发送过来的新的请求体数据)
    req.on('data',(data) => {// 打印请求数据console.log(data)
    })
    
  5. 监听 req 的 end 事件
    当请求体数据接收完毕之后,会自动触发req的end 事件。
    可以在req的end 事件中,拿到并处理完整的请求体数据。
    // 监听 req 对象的 end 事件(请求体发送完毕后自动触发)
    req.on('end',() => {// => 打印完整的请求体数据console.log(str)// TODO: 业务逻辑// .......
    })
    

2.中间件分类

  1. 应用程序级中间件
    通过app.use()或app.get()或 app.post(),绑定到app实例上的中间件,叫做应用级别的中间件,
    var app = express();
    var myLogger = function (req, res, next) {console.log('LOGGED')next()
    }
    // 应用级别的中间件(全局中间件)
    app.use((req, res, next) => {req.name = 'router'req.on('end',() => {console.log('end')})next();
    });
    // 应用级别的中间件(局部中间件)
    app.get('/', myLogger, (req, res) => {console.log(req.name)res.send('Home page.')
    });
    app.listen(8081, function () {console.log("服务启动")
    })
    
    在这里插入图片描述
  2. 路由器级中间件
    绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app实例上,路由级别中绚件摸定到router 实例上
    var express = require('express')
    var app = express()
    var router = express.Router()
    router.use(function (req, res, next) {console.log('Time:', Date.now());next()
    })
    app.use('/', router)
    app.listen(8081, function () {console.log("服务启动")
    })
    
    在这里插入图片描述
  3. 错误处理中间件
    错误处理中间件是专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
    格式:错误级别的中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是(err,req,res,next)。
    注意:错误级别的中间件,必须注册在所有路由之后
    app.get('/', (req, res) => { // 1.路由throw new Error('服务器内部发生了错误');  // 1.1.抛出一个自定义的错误res.send('Home Page.');
    });
    app.use((err, req, res, next) => {    // 2.错误级别的中间件console.log('发生了错误:' + err.message);   // 2.1.在服务器打印错误消息res.send('Erroe!' + err.message); // 2.2.向客户端响应错误相关的内容
    });
    
  4. 内置中间件
    三个内置的中间件分别是
    express.static 是快速托管静态资源的内置中间件 例如:HTML文件、图片、CSS样式等(无兼容性)
    express.json是拿来解析json格式数据的
    express.urlencoded是拿来解析urlencoded格式数据的
    var express = require('express');
    var app = express();
    // 注意这是中间件 所以必须配置到路由之前
    app.use(express.json())
    app.use(express.urlencoded({extended : false}))
    app.listen(8081, function () {console.log("服务启动")
    })
    
  5. 第三方中间件
    非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。
    安装所需功能的 Node.js 模块,然后在应用程序级别或路由器级别将其加载到应用程序中。
    以cookie-parser为示例:
    $ npm install cookie-parser
    
    var express = require('express')
    var app = express()
    var cookieParser = require('cookie-parser')
    app.use(cookieParser())
    

3.自定义中间件

自定义中间件步骤:

  1. 定义中间件
  2. 监听req的data事件
  3. 监听req的end事件
  4. 使用querystring模块解析请求体数据
  5. 将解析出来的数据对象挂载为req.body
  6. 将自定义中间件封装为模块
    // myparse.js
    //1.1 导入内置模块
    const qs=require('querystring')
    //1.2 编写解析函数
    function myparse(req,res,next){//2.2 定义一个变量存储客户端字符串let str=''//2.1 对客户端请求数据的监听//注意是对客户端对象进行监听,而不是服务器req.on('data',(chunk)=>{str+=chunk})//2.4 进行发送数据结束的监听req.on('end',()=>{//倘若有响应,说明数据发送结束,我们已经拿到所有数据console.log(str)//4.2 利用内置模块的parser()进行数据解析const body=qs.parse(str)//4.3 进行数据对象的挂载req.body=bodyconsole.log(body)})//2.5 不要忘记需要调用next函数next()
    }
    //1.4 通过module.exports暴露
    module.exports = myparse
    
    // 使用
    var express = require('express');
    var app = express();
    // 2.1 导入自定义解析模块
    const myparse = require('./mybody-parse')
    app.use(myparse)
    app.get('/login', function (req, res) {console.log(req.body);res.end(req.body);
    })
    

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

港科夜闻 |香港科大推出 InvestLM生成式人工智能平台,支持金融中小企应用AI技术潜力...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大推出 InvestLM生成式人工智能平台,支持金融中小企应用AI技术潜力。香港科大商学院继去年研究团队成功开发本港首个专为金融界而设、应用于生成式人工智能(生成式AI)的开源大语言模型InvestLM后&#…

[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker pull线上镜像方式构建编译环境

T. 已测试目录 主机类型主机版本Docker镜像版本结果WSL2Ubuntu22.04Ubuntu20.04PASSWSL2Ubuntu22.04Ubuntu18.04PASS R. 软硬件要求: 硬件: 设备容量备注硬盘>500G多版本系统测试,必须固态,否则编译卡死硬盘>300G单系统…

Git 快速入门:全面了解与安装步骤

Git 快速入门:全面了解与安装步骤 一、关于Git 1.1 简介 Git 是一个开源的分布式版本控制系统,由 Linus Torvalds 于 2005 年创建,最初是为了更好地管理 Linux 内核开发而设计。 Git用于跟踪计算机文件的变化,特别是源代码文件…

基于Java Springboot奶茶点餐微信小程序

一、作品包含 源码数据库万字文档全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA,微信开发者工具 数据…

vulnhub靶场【哈利波特】三部曲之Fawkes

前言 这次的靶机与前面不同,这里涉及到缓冲区溢出等 这个靶机也让我知道薄弱点了,缓冲溢出这方面之前接触少,所以刚拿到这个靶机打开后,人蒙了,在网上查阅好多资料,也只是浅学一下,这里主要也是…

神经网络中常见的激活函数Sigmoid、Tanh和ReLU

激活函数在神经网络中起着至关重要的作用,它们决定了神经元的输出是否应该被激活以及如何非线性地转换输入信号。不同的激活函数适用于不同的场景,选择合适的激活函数可以显著影响模型的性能和训练效率。以下是三种常见的激活函数:Sigmoid、T…

基于Java Springboot蛋糕订购小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 微信…

<项目代码>YOLOv8 红绿灯识别<目标检测>

YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…

ProtonBase 教育行业解决方案

01/方案概述 当前,大数据、云计算等技术正加速教育行业的数字化转型,教学模式从线下转向线上,传统教育企业向具有互联网性质的新型教育企业转变。在此背景下,教育企业亟需探索多源数据的融合扩展,以应对复杂的业务场景…

Mybatis:CRUD数据操作之删除一行数据

Mybatis基础环境准备请看:Mybatis基础环境准备 本篇讲解Mybati数据CRUD数据操作之单条删除数据 当用户点击了该按钮,就会将改行数据删除掉。那我们就需要思考,这种删除是根据什么进行删除呢?是通过主键id删除,因为id是…

力扣1382:将二叉搜索树便平衡

给你一棵二叉搜索树,请你返回一棵 平衡后 的二叉搜索树,新生成的树应该与原来的树有着相同的节点值。如果有多种构造方法,请你返回任意一种。 如果一棵二叉搜索树中,每个节点的两棵子树高度差不超过 1 ,我们就称这棵二…

架构01-演进中的架构

零、文章目录 架构01-演进中的架构 1、原始分布式时代:Unix设计哲学下的服务探索 (1)背景 时间:20世纪70年代末到80年代初计算机硬件:16位寻址能力、不足5MHz时钟频率的处理器、128KB左右的内存转型:从…

MySQL —— MySQL 程序

目录 前言 一、MySQL 程序简介 二、mysqld -- MySQL 服务器 三、mysql -- MySQL 客户端 1. mysql 客户端简介 2. mysql 客户端选项 (1)指定选项的方式 (2)mysql 客户端命令常用选项 (3)在命令行中使…

GoogleTest做单元测试

目录 环境准备GoogleTest 环境准备 git clone https://github.com/google/googletest.git说cmkae版本过低了,解决方法 进到googletest中 cmake CMakeLists.txt make sudo make installls /usr/local/lib存在以下文件说明安装成功 中间出了个问题就是,…

Flink四大基石之CheckPoint

1、State Vs Checkpoint State:状态,是Flink中某一个Operator在某一个时刻的状态,如maxBy/sum,注意State存的是历史数据/状态,存在内存中。 Checkpoint:快照点, 是Flink中所有有状态的Operator在某一个时刻的State快照信息/存档信息。 一句话概括: Checkpoint就是State的快照…

基于TensorFlow的手写体数字识别训练与测试

需求: 选择一个最简单的细分方向,初步了解AI图像识别的训练、测试过程TensorFlow、PyTorch、c,三种代码方案,先从TensorFlow入手探讨最基本问题的优化问题 总结: 基于TensorFlow的python代码库自带了mnist 训练数据…

YOLO系列论文综述(从YOLOv1到YOLOv11)【第11篇:YOLO变体——YOLO+Transformers、DAMO、PP、NAS】

YOLO变体 1 DAMO-YOLO2 PP-YOLO, PP-YOLOv2, and PP-YOLOE2.1 PP-YOLO数据增强和预处理2.2 PP-YOLOv22.3 PP-YOLOE 3 YOLO-NAS4 YOLO Transformers5 YOLOv1-v8及变体网络结构总结 YOLO系列博文: 【第1篇:概述物体检测算法发展史、YOLO应用领域、评价指标…

SE16N 外键校验报错问题

问题: SE16N维护时,偶尔有一些莫名奇妙的校验报错,条目XX在表XX中不存在,但是实际数据时存在的。 分析: DEBUG过程中,定位到数据校验部分,发现当外键定义的关联字段中存在某些不在对应维护表中…

【数据结构】二叉搜索树(二叉排序树)

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:数据结构 目录 前言 一、什么是二叉搜索树 二、二叉搜索树的实现 节点 属性和接口的声明 插入 查找 删除 拷贝构造 析构 中序遍历 三、二叉搜索树的…

【接口自动化测试】一文从3000字从0到1详解接口测试用例设计

接口自动化测试是软件测试中的一种重要手段,它能有效提高测试效率和测试覆盖率。在进行接口自动化测试之前,首先需要进行接口测试用例的设计。本文将从0到1详细且规范的介绍接口测试用例设计的过程,帮助读者快速掌握这一技能。 一、了解接口…