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

ASP.NET通过Appliaction和Session统计在人数和历史访问量

目录

背景:

Appliaction:

Session:

过程:

数据库:

Application_Start:

Session_Start:

Session_End:

Application_End:


背景:

事件何时激发
Application_Start在调用当前应用程序目录(或子目录)的第一个ASP.NET页面时激发
Applicaiotn_End在应用程序最后一次会话结束时激发,此外在使用Internet服务管理器管理单元停止,Web应用程序时也会激发
Application_BeginRequest在每次页面请求开始时(理论上,在加载或刷新页面)激发
Application_EndRequest在每次页面请求结束时(即每次在浏览器上执行该页面时)激发
Session_Start在每次新的会话开始时激发
Session_End在会话结束时激发

Appliaction:

Application(通常写作Applicaiton)和Session在Wweb开发中各自扮演重要的角色,它们之间既有关联也有区别

Application对象是一个应用级别的对象,主要用于存储和访问来自任何页面的变量,它表示用来保存所有用户(浏览器)共享的数据,直到Web服务器或Pc关闭为止。由于所有的用户共享一个Applicaiton对象,因此它可以用来在所有用户之间共享信息,并可以在Web应用程序运行期间持久地保持数据,如果不加以限制,所有的客户都可以访问这个对象。

Session:

存储用户信息

优点→-包含用户信息

      -在会话中跟踪和监视用户信息

      -会话期满后销毁对象

对象则与特定的用户关联,每个用户都有自己的Session对象,Session用于存储特定用户ADO会话所需的信息,主要用于弥补HTTP协议的不足,因为HTTP协议是一种无状态的协议。Session对象从用户到达某个特定的Web页开始存在,直到该用过户离开Web站点或在程序中利用代码终止某个Session为止,Session的存储是有时效性的,超过设置时间后会被服务器从内存中清除

总的来说Appliction和 Session都是ASP文件公用的对象,用于在多个网页之间保留和使用一些公用信息。它们主要区别于作用的范围和应用场景:Applicaiotn是所有用户共享的,用于全局范围内数据持久化;而Session则是针对单个用户的,用于存储特定用户的会话信息

过程:

数据库:

-- 首先创建一个数据库:  
CREATE DATABASE countpeople; -- 创建数据库  
USE countpeople; -- 转到数据库中  
  
-- 创建表  
CREATE TABLE countepeople (  
    num INT -- 新建字段  
);  
  
-- 插入一条数值为0的记录  
INSERT INTO countepeople VALUES (0);

在ASP.NE中统计在线人数和历史访问人数需要使用四个事件:Applicaiton_Start(),Application_End(),Session_Start()和Session_End();在ASP.NET应用程序启动时,会先触发Application_Start()事件,这是因为Application_Start()事件是在应用程序的全局.asax文件中定义的,并且它是在应用程序开始时被调用的特殊事件。

Application_Start:

在ASP.NET中,当应用程序启动时,会首先触发Global.asax的Applicaiotn_Start()事件,在这个事件中,我们可以增加两个Applicaiotn变量来表示整个程序的公共变量:totalCouont(用来表示总的访问量)和onlineCount(用来表示当前在线人数)

    void Application_Start(object sender, EventArgs e){RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);//上面两行代码,分别用于注册应用程序的路由河 资源捆绑配置,以便于管理 网站的ULR路由和静态资源文件SqlConnection con = new SqlConnection("server=.;database=countPeople;uid=sa;pwd=123;");//数据库连接对象con.Open();//打开数据库连接SqlCommand cmd = new SqlCommand("select * from countPeople", con);//创建SQL查询命令,用于执行查询数据库中countPeple表的所有内容int count = Convert.ToInt32(cmd.ExecuteScalar());//执行SQL查询命令并获得命令并获取查询结果的第一行第一列的值,即数据库中的访问人数,并将其转换为整数类型con.Close();//关闭数据库Application["total"] = count;//查询得到的访问人数存储在应用程序的Application对象中,使用名为"total"的变量表示当前在线人数Application["online"] = 0;  }//初始化在线人数未0,并将其存储在应用程序的Applicaiton对象中,使用名为"online"的变量来表示在线人数

Session_Start:

当每个客户端(浏览器)首次访问服务器时,会触发Session_Start事件,在这个事件中,我们需要让两个"公共变量"totalCount和onlineCount各自自增1",然后,当有多个客户端同时访问时,如果多个请求试图同时更新这些变量,就可能发生数据竞争,导致结果不准确,所以我们为了避免这种情况,我们可以使用Application.Lock()方法来锁定Application对象,确保在任何时候只有一个请求能够修改totalCount和onlineCount。当Applicaiont.Lock()被调用后,任何尝试读取或修改Applicaiont对象的操作都将被阻塞,直到Applicaiotn.UnLock()被调用。这样,就可以保证线程安全地更新这些变量。

   void Session_Start(object sender, EventArgs e){Session.Timeout = 1;//通过设置Session.Timeout=1,将会话时间设置超过一分钟。这意味如果月用户在一分钟内没有活动,则其会话将过期并清除Application.Lock();//使用Application.Lock()方法锁定Applicaiton对象,以确保在同一时刻只有一个请求可以修改Applicaiton对象的状态//防止数据不一致的问题Application["total"] = (int)Application["total"] + 1;//尝试将Application对象中名为"total"的值(总访问量)转换为整数,然后加1,再将结果存回Applicaotn对象中//如果"total"键不存在或不是整数,这行代码会抛出异常Application["online"] = (int)Application["online"] + 1;//与上面类似,尝试将Applicaont对象中名为"onLine"的值(在线人数)转换未整数,然后加1,再将结果存回Application对象中//如果"online"键不存在或不是整数,这行代码也会抛出异常Application.UnLock();}//使用Applicaotn.UnLokc()方法解除对Application对象的锁定,允许其他请求修改Application对象的状态

现在,我们已经 统计出了在线人数和历史访问数量,这连个值存储在Application对象。当需要在页面上显示这些值时,我们可以直接通过访问Applicaiton["变量名"]来获取它们。我的是在Label控件上显示人数和历史记录,我建了一个Default窗体拖拽了两个控件一个lable1和label2,用来在窗体显示历史记录和在线人数,直接将Applicaiton["onLine"]的值转换未字符串并赋值给Label的Text属性;

            protected void Page_Load(object sender, EventArgs e){this.lblTotal.Text = Application["total"].ToString();//历史记录this.lblOneLine.Text = Application["online"].ToString();//在线人数 }

Session_End:

注意一点,因为Applicaiotn对象中存储的变量值都是Object类型的,所以当我们从Application中取出值时,我们需要确保进行正确的类型转换。如果Application["onLine"]不是一个可以转换未字符串的对象,上面的代码将会抛出异常。因此,通常我们会检查该值是否存在,并确认其类型,然后再进行转换和显示,Aapplicaiton["total"也是一样]
当一个客户端(浏览器)与服务器的会话结束时,会触发Session_End事件。在这个事件中,我们不需要修改历史访问数量,但是在线人数需要减1,以反应当前活跃的会话数量减少了。在Session_End事件中,我们可以编写如下代码来更新在线人数

       void Session_End(Object sender, EventArgs e){Application.Lock();//锁定Applicaiotn对象。Lock方法确保在当前线程释放锁之前,其他线程不能修改Applicaiotn对象//在ASP.NET中,Applicaiton对象是一个全局对象,它允许在整个Web应用程序中存储和访问数据。由于多个线程可能同时访问和修改Application对象的数据,为了避免数据不一致或竞争条件(race conditions),你要在使用它之前先锁定它。Lock方法确保了在当前线程释放锁之前,其他线程不能修改Applicaiotn对象。Application["online"] = (int)Application["online"] - 1;//它从Application对象中获取键为"online"的值,并假设这个值是一个整数(int)//它将这个整数值减1,然后将结果存回Application对象中,仍然使用键"online"//用于跟踪当前在线的用户数,每当一个会话结束时(通过Session_End事件来监测),在线用户就回减少。需要注意的是,直接进行类型转换(int)前应该检查该值是否确实存在且可以被转换为整数以避免运行时错误Application.UnLock();}//解锁Application对象的。一旦你完成了对Application对象的修改,就应该立即解锁它,以便其他线程可以访问和修改它。忘记解锁Application对象可能会导致性能问题,因为其他线程将被阻塞,等待锁被释放。

Application_End:

如果服务器要关闭,历史总人数我们是不是要保存,再次登录的时候历史记录人数累加起来,所以我们就要把目前Application中存储的历史访问总数更新到数据库中,在Applicaiton_End()事件中进行:

   void Application_End(Object sender, EventArgs e)//定义一个SqlConnection对象conn,用于与数据库进行连接。连接字符串指定了数据库服务器、数据库名称、用户名和密码{ SqlConnection con = new SqlConnection("server=.;database=countPeople;uid=sa;pwd=123;");//这行代码创建了一个SqlConnection对象con,用于与数据库进行连接。连接字符串指定了数据库服务器、数据库名称、用户名和密码con.Open();//这行代码打开了数据库的连接,以便后续可以执行数据库操作SqlCommand cmd = new SqlCommand("update  countPeople set num=" + Application["total"].ToString(), con);//创建一个SqlCommand对象cmd,用于执行sql语句, SQL语句是一个更新语句,将应用程序对象中存储"total"值更新到countPeople的num字段中cmd.ExecuteNonQuery();//执行了SQL更新语句,将应用程序对象存储"totle"值更新到数据库中con.Close();

到这里大家肯定有个疑问,假如您现在是在Visual Studio 2022中,关闭系统时,并没有触发Applicaiotn_End事件,历史记录人数并没有被写到数据库。那么该如何操作才能让Application_End事件触发呢,本人找到两种方法
第一种办法:
当你运行Visual Studio 2022的时候,你的电脑右小角又会又一个IIS EXpress的图标,选中查看所有应用程序,然后停止正在运行得程序,也可以登录IIS主界面去停止程序。

第二种办法:

当应用程序域结束时,Application_End 方法会自动执行,而不需要手动触发。但是,您可以通过模拟应用程序域重新加载的方式来测试 Application_End 方法。

在代码中手动调用 HttpRuntime.UnloadAppDomain() 方法来模拟应用程序域的重新加载,从而间接地触发 Application_End 方法执行。

详细步骤:

在 ASP.NET 项目中的 Global.asax 文件。

 Application_End 方法中添加这行代码

void Application_End(object sender, EventArgs e)
{System.Diagnostics.Debug.WriteLine("应用程序结束于:" + DateTime.Now.ToString());
}

在您的代码中的某个地方,调用 HttpRuntime.UnloadAppDomain() 方法来模拟应用程序域的重新加载。我是显示历史记录和在线人数得界面上,添加了一个Button按钮

protected void Button1_Click(object sender, EventArgs e)
{// 模拟应用程序域的重新加载System.Web.HttpRuntime.UnloadAppDomain();
}

运行您的应用程序,并在触发了 HttpRuntime.UnloadAppDomain() 方法的位置进行操作。您将看到在应用程序重新加载时,Application_End 方法会执行,并且其中的代码逻辑将被触发。
通过以上步骤,您可以在开发和测试环境中模拟应用程序域的重新加载,从而验证 Application_End 方法的执行情况。请记住,在生产环境中要小心谨慎,避免频繁手动触发应用程序域的重新加载。


注意:只是在服务器上停止该程序的运行才会触发Application_End()事件,重启和断电等情况并不能触发



 

相关文章:

ASP.NET通过Appliaction和Session统计在人数和历史访问量

目录 背景: Appliaction: Session: 过程: 数据库: Application_Start: Session_Start: Session_End: Application_End: 背景: 事件何时激发Application_Start在调用当前应用…...

在基于全志V851se的TinyVision上手动构建 Linux 6.1 + Debian 12 镜像

构建 SyterKit 作为 Bootloader SyterKit 是一个纯裸机框架,用于 TinyVision 或者其他 v851se/v851s/v851s3/v853 等芯片的开发板,SyterKit 使用 CMake 作为构建系统构建,支持多种应用与多种外设驱动。同时 SyterKit 也具有启动引导的功能&a…...

使用jenkins-pipeline进行利用项目文件自动化部署到k8s上

Discard old builds:丢弃旧的构建,目的是管理存储空间、提升性能以及保持环境整洁 Do not allow concurrent builds: 禁止并发构建是指同一时间内只允许一个构建任务执行,避免多个构建同时运行可能带来的问题 Do not allow the pipeline to resume if the controller resta…...

unity发布安卓获取读取权限

一、Player Settings 设置 Player Settings>Player>Other Settings> Android > Write Permission > External (SDCard). 二、代码 using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Andr…...

VSCode下使用github初步

由于各种需要,现在需要统一将一些代码提交搞github,于是有了在VSCode下使用github的需求。之前只是简单的使用git clone,代码提交这些用的是其他源代码工具,于是得学习实操下,并做一记录以备后用。 安装 VSCode安装 …...

华为设备配置命令大全

目录 一、华为设备常用命令视图 二、返回命令和保存命令 三、设置设备名称 四、关闭泛洪信息 五、设置设备接口的IP地址和子网掩码 六、交换机的登录 6.1、设置Consile接口密码 6.2、设置Telent接口密码 七、VLAN配置 7.1、创建VLAN 7.2、进入vlan视图 7.3、把端口…...

详解基于快速排序算法的qsort的模拟实现

目录 1. 快速排序 1.1 快速排序理论分析 1.2 快速排序的模拟实现 2. qsort的模拟实现 2.1 qsort的理论分析 2.2 qsort的模拟实现 qsort函数是基于快速排序思想设计的可以针对任意数据类型的c语言函数。要对qsort进行模拟实现,首先就要理解快速排序。 1. 快…...

鸿蒙Harmony应用开发—ArkTS声明式开发(绘制组件:Polyline)

折线绘制组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Polyline(value?: {width?: string | number, height?: string | number}) 从API version 9开始&#xff0c…...

项目风险管理

项目风险管理 1 规划风险管理2 识别风险1.2 输出 3 实施定性风险分析3.1 输入3.2 输出 4 实施定量风险分析4.1 输入4.2 输出 5 规划风险应对5.1 输入5.2 输出 6 实施风俗应对6.1 输入6.2 输出 7 监督风险7.1 输入7.2 输出 项目风险是一种不确定的事件或条件,一旦发生…...

glib交叉编译

Glib交叉编译 逸一时,误一世。 —— 田所浩二「夏夜银梦」 交叉编译 GLib 涉及到在一个平台上生成能够在另一个平台上运行的目标文件。在这种情况下,我们将会在一台主机(通常是开发机器)上使用交叉编译工具链来构建 GLib 库&#…...

Android11实现能同时开多个录屏应用(或者共享屏幕或投屏时录屏)

1.概述 Android原生对MediaProjection的管理逻辑,是如果服务端已经保存有MediaProjection的实例,那么再次创建的时候,之前的MediaProjection实例就会被暂停,并且引用指向新的实例,也就导致了当开启后一个录屏应用时&a…...

音视频实战---音频重采样

1、使用swr_alloc()创建重采样实例 2、使用av_opt_set_int函数设置重采样输入输出参数 3、使用swr_init函数初始化重采样器 4、使用av_get_channel_layout_nb_channels函数计算输入源的通道数 5、给输入源分配内存空间–av_samples_alloc_array_and_samples 6、计算输出采…...

主存中存储单元地址的分配

主存中存储单元地址的分配 为什么写这篇文章? 因为我看书中这部分时,看到下面的计算一下子没反应过来: 知识回顾(第1章) 计算机系统中,字节是最小的可寻址的存储单位,通常由8个比特(bit&…...

Python和R的区别是什么,Python与R的应用场景是什么?

如果你这么问,那么你可能正站在数据科学的起点。对于志在成为数据专业人员的你来说,学习编程是无疑的。我想行你早就听过Python 与R的比较之声,并在选择中感到困惑。在此,我想说,也算是一种安慰吧:对于语言…...

azure databricks 常用的JDBC连接

做个笔记常用的spark-jdbc连接 1、mysql 的连接 def query_mysql(database,sqlstr):jdbcUsernamejdbcHostname " "jdbcDatabase ""jdbcPort 3306mysql_df spark.read \.format("jdbc") \.option("driver","com.mysql.cj.jdb…...

功能齐全的免费 IDE Visual Studio 2022 社区版

面向学生、开放源代码和单个开发人员的功能齐全的免费 IDE 下载地址 Visual Studio 2022 社区版 - 下载最新的免费版本 Visual Studio 2022 Community Edition – Download Latest Free Version 准备安装 选择需要安装的程序 安装进行中 使用C学习程序设计相关知识并培养编程…...

FreeRTOS入门基础

RTOS是为了更好地在嵌入式系统上实现多任务处理和时间敏感任务而设计的系统。它能确保任务在指定或预期的时间内得到处理。FreeRTOS是一款免费开源的RTOS,它广泛用于需要小型、预测性强、灵活系统的嵌入式设备。 创建第一个任务 任务函数:任务是通过函数…...

蓝桥杯-24点-搜索

题目 思路 --暴力递归全组合的方法。只有4个数,4种计算方式,共有4 * 3 * 2 * 1 * 4种不同的情况,可以写递归来实现。 --每次计算都是两个数之间的运算,因此4个数需要3次计算,第一次计算前有4个数,第二次有…...

【附下载】3Ds Max从安装、配置到入门提高和高级用法

#3Ds Max 一、安装 1.1 安装说明 地址:链接:https://pan.baidu.com/s/1lwKMbgbE32wCL6PpMv706A?pwddll8 提取码:dll8 –来自百度网盘超级会员V2的分享 安装说明:文件夹里有安装说明 安装解压即可 关键就是将crack文件放到自己…...

开源堡垒机Jumpserver

开源堡垒机Jumpserver 文章目录 开源堡垒机Jumpserver1 Jumpserver介绍2 Jumpserver部署用户管理资产创建账号管理模板添加 用户组管理权限管理远程连接免密连接 1 Jumpserver介绍 Jumpserver 是全球首款完全开源的堡垒机,使用 GNU GPL v2.0 开源协议,是…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

ip子接口配置及删除

配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...

Python的__call__ 方法

在 Python 中,__call__ 是一个特殊的魔术方法(magic method),它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时(例如 obj()),Python 会自动调用该对象的 __call__ 方法…...

shell脚本质数判断

shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数)shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数) 思路: 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...