鸿蒙网络编程系列32-基于拦截器的性能监控示例

1. 拦截器简介

在Web开发中拦截器是一种非常有用的模式,它允许开发者在请求发送到服务器之前或响应返回给客户端之前执行一些预处理或后处理操作。这种机制特别适用于需要对所有网络请求或响应进行统一处理的情况,比如添加全局错误处理、请求头的修改、响应数据的格式化等,本示例将使用RCP模块提供的拦截器功能,实现对HTTP请求的性能监控,为简单起见,本示例只记录每个HTTP请求和响应的时间以及相关的状态信息,读者可以根据需要记录更多的信息并在此基础上进行深入的统计分析。

在RCP模块的API中,拦截器是以接口的形式提供的,接口名称为Interceptor,包括名称为intercept的一个方法:

intercept(context: RequestContext, next: RequestHandler): Promise<Response>

该方法第一个参数context为请求上下文,第二参数next为下一个请求处理器,可以返回Response的Promise对象,或者返回next调用handle方法的值。

2. 拦截器性能监控演示

本示例运行后的界面如图所示:

这里列出了5个可以请求的web地址,输入要请求的次数,然后单击“随机请求”按钮,应用会随机请求地址列表中的web地址,拦截器会在下方的日志区域实时显示请求性能信息,如图所示:

3. 拦截器性能监控示例编写

下面详细介绍创建该示例的步骤。
步骤1:创建Empty Ability项目。
步骤2:在module.json5配置文件加上对权限的声明:

"requestPermissions": [{"name": "ohos.permission.INTERNET"}]

这里添加了访问互联网的权限。
步骤3:在Index.ets文件里添加如下的代码:

import { rcp } from '@kit.RemoteCommunicationKit';@ObservedV2//拦截日志类
class RequestPerfRecord {@Trace public id: string = ""@Trace public method: string = ""@Trace public begin: Date = new Date()@Trace public end: Date = new Date()@Trace public requestUrl: string = ""@Trace public stateCode: number = -1constructor(request: rcp.Request) {this.id = request.idthis.method = request.methodthis.begin = new Date()this.requestUrl = request.url.toString()}//请求耗费的秒数public spendTime(): number {return (this.end.valueOf() - this.begin.valueOf()) / 1000}public toString(): string {if (this.stateCode == -1) {return `请求地址:${this.requestUrl}\r\n请求方法:${this.method}\r\n` +`请求开始时间:${this.begin.toLocaleString()} \r\n`} else {return `请求地址:${this.requestUrl}\r\n请求方法:${this.method}\r\n` +`请求开始时间:${this.begin.toLocaleString()}\r\n响应时间:${this.end.toLocaleString()} \r\n` +`请求响应耗时:${this.spendTime()}秒\r\n` +`响应状态码:${this.stateCode}\r\n`}}
}@Entry
@ComponentV2
struct Index {@Local title: string = '基于拦截器的HTTP请求性能监控';//请求地址列表@Local requestUrlList: Array<string> =["https://www.baidu.com", "https://www.baidu.com/nopage.html", "https://www.aliyun.com/", "https://developer.huawei.com/consumer/cn/forum/", "https://www.zhihu.com/"]//请求次数@Local requestTimes: number = 5//拦截日志列表@Local requestPerRecordList: Array<RequestPerfRecord> = new Array()scroller: Scroller = new Scroller()build() {Row() {Column() {Text(this.title).fontSize(14).fontWeight(FontWeight.Bold).width('100%').textAlign(TextAlign.Center).padding(5)Text("请求地址列表:").fontSize(14).width('100%').padding(5)List({ space: 5, initialIndex: 0 }) {ForEach(this.requestUrlList, (item: string) => {ListItem() {Text(item).fontSize(13)}}, (item: string) => item)}.width('100%').padding(5)Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {Text("请求次数:").fontSize(14).width(80)Counter() {Text(this.requestTimes.toString())}.onInc(() => {this.requestTimes++}).onDec(() => {this.requestTimes--}).width(140).padding(10).height(50)Button("随机请求").onClick(() => {this.requestTest()}).width(100).fontSize(14)}.width('100%').padding(5)Scroll(this.scroller) {List({ space: 5, initialIndex: 0 }) {ForEach(this.requestPerRecordList, (item: RequestPerfRecord) => {ListItem() {Text(item.toString()).fontSize(13)}}, (item: string) => item)}.width('100%').padding(5)}.align(Alignment.Top).backgroundColor(0xeeeeee).height(300).flexGrow(1).scrollable(ScrollDirection.Vertical).scrollBar(BarState.On).scrollBarWidth(20)}.width('100%').justifyContent(FlexAlign.Start).height('100%')}.height('100%')}async requestTest() {let cfg: rcp.SessionConfiguration = {interceptors: [new PerfInterceptor(this.requestPerRecordList)]}const session = rcp.createSession(cfg);for (let i = 0; i < this.requestTimes; i++) {let index = Math.floor(Math.random() * this.requestUrlList.length)await session.get(this.requestUrlList[index])let sleepTime = Math.random() * 5 + 1await sleep(sleepTime)}}
}//休眠指定的毫秒数
function sleep(time: number): Promise<void> {return new Promise((resolve) => setTimeout(resolve, time));
}//性能监控拦截器
class PerfInterceptor implements rcp.Interceptor {requestPerList: Array<RequestPerfRecord>constructor(requestPerList: Array<RequestPerfRecord>) {this.requestPerList = requestPerList}//拦截方法async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {let record = new RequestPerfRecord(context.request)this.requestPerList.push(record)const promise = next.handle(context);promise.then((resp) => {record.stateCode = resp.statusCode;record.end = new Date()});return promise;}
}

步骤4:编译运行,可以使用模拟器或者真机。

步骤5:按照本节第1部分“拦截器性能监控演示”操作即可。

4. 代码分析

本示例的关键点在于记录HTTP请求及响应的时间,这是通过拦截器的intercept方法实现的,该方法首先记录当前的时间,也就是请求发起的时间,然后调用next的handle方法,该方法会发起HTTP请求并返回响应,在该方法的响应处理回调函数中,再次记录当时的时间,也就是响应返回的时间,这样就拿到了最关键的两个时间信息,具体代码如下所示:

async intercept(context: rcp.RequestContext, next: rcp.RequestHandler): Promise<rcp.Response> {let record = new RequestPerfRecord(context.request)this.requestPerList.push(record)const promise = next.handle(context);promise.then((resp) => {record.stateCode = resp.statusCode;record.end = new Date()});return promise;}

另外,因为需要把记录的信息在应用界面上展示,所以把状态变量requestPerRecordList传递到了拦截器实例中,这样拦截器生成的HTTP请求日志信息也就保存到了requestPerRecordList变量中,从而可以在界面上随时看到拦截日志。

(本文作者原创,除非明确授权禁止转载)

本文源码地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/rcp/HttpRequestMonitor

本系列源码地址:
https://gitee.com/zl3624/harmonyos_network_samples

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

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

相关文章

PostgreSQL中触发器递归的处理 | 翻译

许多初学者在某个时候都会陷入触发器递归的陷阱。通常&#xff0c;解决方案是完全避免递归。但对于某些用例&#xff0c;您可能必须处理触发器递归。本文将告诉您有关该主题需要了解的内容。如果您曾经被错误消息“超出堆栈深度限制”所困扰&#xff0c;那么这里就是解决方案。…

电脑视频剪辑大比拼,谁更胜一筹?

随着短视频的火爆&#xff0c;越来越多的人开始尝试自己动手制作视频&#xff0c;无论是记录生活点滴还是创作个性短片&#xff0c;一款好用的视频剪辑软件是必不可少的。今天&#xff0c;我们就从短视频运营的角度&#xff0c;来聊聊几款热门的电脑视频剪辑软件&#xff0c;看…

FineReport 数据筛选过滤

从大量的数据当中&#xff0c;获取到符合条件的数据&#xff0c;经常会使用到数据筛选过滤功能&#xff0c;在FineReort产品中实现筛选过滤的方法有三种 1&#xff09;直接通过 SQL 语句取出满足条件的的数据&#xff0c;如修改数据集 SQL 语句为&#xff1a;SELECT * FROM 订单…

YOLOv8改进,YOLOv8采用WTConv卷积(感受野的小波卷积),二次创新C2f结构,ECCV 2024

摘要 WTConv(基于小波变换的卷积层),用于在卷积神经网络(CNN)中实现大感受野。作者通过利用小波变换,设计了一个卷积层,可以在保持少量可训练参数的情况下大幅扩大感受野。WTConv 被设计为可以无缝替换现有 CNN 架构中的深度卷积层,适用于图像分类、语义分割、物体检测…

Vue-插槽slot

当我们封装一个组件时&#xff0c;不希望里面的内容写死&#xff0c;希望使用的时候能够自定义里面的内容&#xff0c;这时我们就需要使用到插槽 插槽是什么呢 插槽是子组件提供给父组件的一个占位符&#xff0c;用slot标签表示&#xff0c;父组件可以在这个标签填写任何模板代…

3DMAX碎片生成器插件FragmentGenerator使用方法

3DMAX碎片生成器FragmentGenerator插件&#xff0c;主要应用于科研绘图方面&#xff0c;一键从选择对象体积上生成若干不规则大小凌乱排列的三角形面。 【适用版本】 3dMax2015 – 2025&#xff08;不仅限于此范围&#xff09; 【安装方法】 FragmentGenerator插件无需安装&a…

基于vue框架的的二手数码产品回收管理系统bodx1(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,产品分类,产品信息,预约回收,回收员,产品回收 开题报告内容 基于Vue框架的二手数码产品回收管理系统开题报告 一、课题背景及意义 随着科技的快速发展和消费者生活水平的提高&#xff0c;数码产品的更新换代速度日益加快&#x…

网络安全中的日志审计:为何至关重要?

在数字化时代&#xff0c;网络安全已成为企业和组织不可忽视的重要议题。随着网络攻击手段的不断进化&#xff0c;保护信息系统和数据安全变得日益复杂和具有挑战性。在这种背景下&#xff0c;日志审计作为一种关键的信息安全和网络管理工具&#xff0c;发挥着至关重要的作用。…

软考(网工)——局域网和城域网

文章目录 &#x1f550;局域网基础1️⃣局域网和城域网体系架构 IEEE&#xff08;负责链路层&#xff09;2️⃣局域网拓扑结构 &#x1f551;CSMA/CD1️⃣CSMA/CD2️⃣CSMA/CD三种监听算法3️⃣冲突检测原理 &#x1f552;二进制指数退避算法1️⃣ 二进制指数退避算法 &#x1…

envoyFilter导致的webSockets协议无法正常工作

一、背景 生产项目有一个socket请求经过网关一直无法响应&#xff0c;其它接口服务都能正常处理。 二、 处理过程 让租户提供对应的模拟请求接口&#xff0c;然后进行模拟请求测试&#xff0c;并查看envoy网关日志&#xff0c;发现在发起请求时&#xff0c;envoy网关日志是无法…

解密 Redis:如何通过 IO 多路复用征服高并发挑战!

文章目录 一、什么是 IO 多路复用&#xff1f;二、为什么 Redis 要使用 IO 多路复用&#xff1f;三、Redis 如何实现 IO 多路复用&#xff1f;四、IO 多路复用的核心机制&#xff1a;epoll五、IO 多路复用在 Redis 中的工作流程六、IO 多路复用的优点七、IO 多路复用使用中的注…

CTF(四)

导言&#xff1a; 本文主要讲述在CTF竞赛中&#xff0c;web类题目file_include。 靶场链接&#xff1a;攻防世界 (xctf.org.cn) 一&#xff0c;观察页面。 可以看到一段php代码。从则段代码中我们可以知道&#xff1a; 1&#xff0c;使用include引入check.php文件&#xff…

排序算法 —— 快速排序(理论+代码)

目录 1.快速排序的思想 2.快速排序的实现 hoare版 挖坑法 前后指针法 快排代码汇总 3.快速排序的优化 三数取中 小区间优化 三路划分 4.快速排序的非递归版本 5.快速排序总结 1.快速排序的思想 快速排序是一种类似于二叉树结构的排序方法。其基本思想为从待排序序…

【前端】如何制作一个自己的网页(15)

有关后代选择器的具体解释&#xff1a; 后代选择器 后代选择器使用时&#xff0c;需要以空格将多个选择器间隔开。 比如&#xff0c;这里p span&#xff0c;表示只设置p元素内&#xff0c;span元素的样式。 <style> /* 使用后代选择器设置样式 */ p span { …

给EXE添加网络验证激活码(卡密)

介绍 网络验证可以理解为给EXE文件添加一个激活码, 用户在打开EXE文件时, 需要输入激活码, 输入后, 通过网络验证激活码, 如果激活码有效用户便可以继续使用软件. 网络验证可以生成静态激活码(也就是卡密), 再需要使用的时候直接发给用户即可, 无需像离线一机一码加密那样需要…

漏洞挖掘 | 基于mssql数据库的sql注入

前记 今天挖edu随意点开个站&#xff0c;发现存在mssql数据库的sql注入&#xff0c;在此分享下整个挖掘过程 目录 0x1 判断网站数据库类型 0x2 了解mssql数据库的主要三大系统表 0x3 了解mssql的主要函数 0x4 判断注入点及其注入类型 0x5 联合查询之判断列数 0x6 联合查询之…

spring源码拓展点3之addBeanPostProcesser

概述 在refresh方法中的prepareBeanFactory方法中&#xff0c;有一个拓展点&#xff1a;addBeanPostProcessor。即通过注入Aware对象从而将容器中的某些值设置到某个bean中。 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));aware接口调用 …

华为配置 之 Console线路配置

目录 简介&#xff1a; 知识点&#xff1a; 配置Console线路密码 1.密码认证模式 2.AAA认证模式 知识点&#xff1a; 总结&#xff1a; 简介&#xff1a; 使用PC模拟器与路由器相连&#xff08;与交换机相连原理一样&#xff09;&#xff0c;在关机状态下&#xff0c;使用…

手机玩黑色沙漠?GameViewer远程玩黑色沙漠教程

黑色沙漠的国服即将在10月24日迎来公测&#xff01;这是一款玩法多元的大型多人在线角色扮演游戏&#xff0c;你可以享受激烈的战斗&#xff0c;也可以感受惬意的生活&#xff0c;在这个游戏里你能体验到一个不一样的冒险故事。不管你是老玩家还是新玩家&#xff0c;只要你想玩…

鸿蒙开发:实现一个超简单的网格拖拽

前言 网格拖拽&#xff0c;此功能很是常见&#xff0c;一般用于频道的编辑或者条目顺序的排列&#xff0c;在鸿蒙的开发中&#xff0c;针对网格的编辑&#xff0c;系统也给出了相关的Api&#xff0c;通过onItemDragStart和在onItemDrop即可轻松实现&#xff0c;onItemDragStart…