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()事件,重启和断电等情况并不能触发



 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

REDHAWK——连接(续)

文章目录 前言一、突发 IO1、数据传输①、输入②、输出 2、突发信号相关信息 (SRI)3、多输出端口4、使用复数数据①、在 C 中转换复数数据 5、时间戳6、端口统计①、C 二、消息传递1、消息生产者①、创建一个消息生产者②、发送消息 2、消息消费者①、创建消息消费者②、注册接…

Ruoyi前后端分离项目部署至Tomcat上

项目部署 4.1.前端打包 disaster-ui目录下为本项目的前端所在位置,在命令行窗口进入该目录,然后输入npm run build:prod部署前端Vue项目,或者直接在disaster-ui/bin目录下双击build.bat文件部署前端。 图 4-1 前端部署图 4.2 环境变量 在MySQL可视化…

Vmware虚拟机配置虚拟网卡

背景 今天同事咨询了我一个关于虚拟机的问题,关于内网用Vmware安装的虚拟机,无法通过本机访问虚拟上的Jenkins的服务。   验证多次后发现有如下几方面问题。 Jenkins程序包和JDK版本不兼容(JDK1.8对应Jenkins不要超过2.3.57)虚…

LeetCode每日一题[C++]-303.区域和检索-数组不可变

题目描述 给定一个整数数组 nums&#xff0c;处理以下类型的多个查询: 计算索引 left 和 right &#xff08;包含 left 和 right&#xff09;之间的 nums 元素的 和 &#xff0c;其中 left < right 实现 NumArray 类&#xff1a; NumArray(int[] nums) 使用数组 nums 初…

微信小程序简单实现手势左右滑动和点击滑动步骤条功能

使用微信小程序实现左右滑动功能&#xff0c;自定义顶部图案&#xff0c;点击文字滑动和手势触屏滑动&#xff0c;功能简单&#xff0c;具体实现代码如下所示&#xff1a; 1、wxss代码&#xff1a; /* 步骤条 */ .tab-box {display: flex;flex-direction: row;position: fix…

LVS+Keepalived 高可用群集--部署

实际操作 LVS Keepalived 高可用群集 环境设备 LVS1192.168.6.88 &#xff08;MASTER&#xff09;LVS2192.168.6.87 &#xff08;BACKUP&#xff09;web1192.168.6.188web2192.168.6.189客户端192.168.6.86VIP192.168.6.180 &#xff08;一&#xff09;web服务器 首先配置…

华为汽车业务迎关键节点,长安深蓝加入HI模式,车BU预计今年扭亏

‍编辑 |HiEV 一年之前&#xff0c;同样是在电动汽车百人会的论坛上&#xff0c;余承东在外界对于华为和AITO的质疑声中&#xff0c;第一次公开阐释了华为选择走智选车模式的逻辑。 一年之后&#xff0c;伴随问界M7改款、问界M9上市&#xff0c;华为智选车模式的面貌已经发生了…

Python基于深度学习的中文情感分析系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Javaweb的学习19_CSS概念+css与html的结合方式

CSS CSS&#xff1a;页面美化和布局控制 1. 概念&#xff1a;Cascading Style Sheets 层叠样式表 层叠&#xff1a;多个样式可以作用在同一个html的元素(标签)上&#xff0c;同时生效 2. 好处&#xff1a; 1.功能强大 2.将内容展示(HTML)和样式控制(CSS)分离 *降低耦合度。解耦…

第十八届全国大学生智能汽车竞赛——摄像头算法(附带个人经验)

文章目录 前言一、摄像头图像处理1、摄像头图像采集2、图像二值化与大津算法 二、左右边界&#xff0c;中线扫描 前言 参加了第十六&#xff0c;十七和第十八届全国大学生智能车竞赛&#xff0c;对摄像头的学习有部分心得&#xff0c;分享给大家&#xff0c;三届车赛&#xff…

算法第三十天-矩阵中移动的最大次数

矩阵中移动的最大次数 题目要求 解题思路 网格图 DFS 从第一列的任一单元格 ( i , 0 ) (i,0) (i,0) 开始递归。枚举往右上/右/右下三个方向走&#xff0c;如果走一步后&#xff0c;没有出界&#xff0c;且格子值大于 g r i d [ i ] [ j ] grid[i][j] grid[i][j]&#xff0c;则…

堆叠与集群

8.1堆叠与集群概述 随着企业的发展&#xff0c;企业网络的规模越来越大&#xff0c;这对企业网络提出了更高的要求&#xff1a;更高的可靠性、更低的故障恢复时间、设备更加易于管理等。传统的园区网高可靠性技术出现故障时切换时间很难做到毫秒级别、实现可靠性的方案通常为一…

YOLOv8改进算法之添加CA注意力机制

1. CA注意力机制 CA&#xff08;Coordinate Attention&#xff09;注意力机制是一种用于加强深度学习模型对输入数据的空间结构理解的注意力机制。CA 注意力机制的核心思想是引入坐标信息&#xff0c;以便模型可以更好地理解不同位置之间的关系。如下图&#xff1a; 1. 输入特…

敏捷开发——elementUI/Vue使用/服务器部署

1. 创建vue项目 2. 安装element-ui组件库 npm i -S element-ui或 npm install element-ui3. 在main.js中导入element-ui组件 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css Vue.use(ElementUI)4. 运行 npm run serve后可以使用 ctrc终止进…

一个 Java8 的坑坑了我 2 小时试错...

背景 趁着失业的间隙想要重温一下Flink相关的学习&#xff0c;当前一切就绪之后&#xff0c;想要用我的 mac运行一个 flink版 helloworld 来验证整体环境是否 OK的时候出现了如下问题&#xff0c;这个问题我未曾遇到过&#xff0c;如下&#xff1a; Failed to write core dump…

【iOS】Blocks

文章目录 前言一、什么是Blocks二、Blocks模式1.Block语法2.Block类型变量3.截获自动变量值4.__block说明符5.截获的自动变量 三、Blocks的实现1.Block的实质__main_block_impl_0Block对象的实现结构体初始化 2.截获自动变量值3.__block说明符4.Block存储域5.__block变量存储域…

LM studio使用gemmar聊天小试

通过LM studio可以方便的使用各种模型&#xff0c;使用LM提供的chat界面或者是使用python代码。 试试代码 在windows下使用python简单一试&#xff0c;例子直接复制LM界面上的代码&#xff1a; 用pip安装 openai包在LM界面 Start Server 需要安装 openai包。 本地电脑是I7…

ArcGIS巧思制作3D景观地图

John Nelson 又制作了一个制图教程视频,我原以为只是一个简单的局部场景DEM夸张实现的3D地图。 不过细看以后…… 还就是比较简单的3D场景地图,操作不难,但是 John Nelson 就是天才。 为什么? 他使用 ArcGIS Pro,在普通的3D地图中,不仅仅是图层混合制作地形效果,还巧妙的…

GPT实战系列-LangChain的Prompt提示模版构建

GPT实战系列-LangChain的Prompt提示模版构建 LangChain GPT实战系列-LangChain如何构建基通义千问的多工具链 GPT实战系列-构建多参数的自定义LangChain工具 GPT实战系列-通过Basetool构建自定义LangChain工具方法 GPT实战系列-一种构建LangChain自定义Tool工具的简单方法…

LLM 构建Data Multi-Agents 赋能数据分析平台的实践之②:数据治理之一

概述 数据治理不仅是产业数字化转型的基石&#xff0c;更是推动产业向更高层次、更精细化、更智能的方向发展的重要引擎。通过科学有效的数据治理实践&#xff0c;产业能够在数字化进程中实现数据驱动的决策与行动&#xff0c;最终达到转型升级的战略目标。 一、数据治理在产业…